Статьи

Звездочки рассеяны: метки активов

sprocketsmag

Rails — это любимый веб-фреймворк Ruby и популярный выбор для создания веб-приложений. Он имеет множество замечательных частей, многие из которых можно использовать независимо от Rails. Например, ActiveSupport можно использовать в любом проекте Ruby для получения некоторых замечательных функций, которые предоставляет ядро ​​Rails. ActiveRecord — это автономный ORM, обеспечивающий надежный способ работы с различными базами данных с помощью одной кодовой базы.

Есть еще один компонент Rails, который широко используется за пределами Rails: конвейер активов или, технически говоря, Sprockets. Sprockets — это драгоценный камень Ruby, разработанный Сэмом Стивенсоном, который предоставляет поддержку для компиляции активов, минимизации активов, обслуживания активов и многого другого. В этой статье мы обсудим, как Rails обслуживает активы с помощью Sprockets.

Я бы порекомендовал прочитать, как работает прекомпиляция активов, часть I и как работает прекомпиляция активов, часть II, прежде чем продолжить Здесь используется много концепций, которые подробно обсуждаются в этих статьях.

Эта статья основана на Rails 3.2.17 и Sprockets 2.2.2 . Пожалуйста, сначала установите Rails 3.2.17 если вы этого еще не сделали.

Давайте ответим на следующие вопросы, связанные с активами Rails:

  • Как вставляются теги активов?
  • Что такое /assets и их назначение?
  • Для чего используется ActionDispatch::Static middleware?

Как вставляются метки активов?

Первый шаг к обслуживанию актива — наличие правильных тегов ресурса (тегов JavaScript, тегов таблицы стилей, тегов изображений и т. Д.) В ответе HTML, отправляемом клиенту. Если в HTML нет тегов ресурсов, то мы не используем / не связываем никакие внешние библиотеки, что в настоящее время довольно табу. Нам нужен как минимум один тег Stylesheet, один тег JavaScript и несколько тегов изображений на нашем сайте. Давайте посмотрим, как тег JavaScript вставляется в ответ HTML, сгенерированный из типичного приложения Rails.

Пути к исходному коду упоминались как локальные, так и онлайн, в зависимости от ситуации. Здесь интерес представляют две папки, которые можно обнаружить с помощью следующих команд в приложении Rails:

 bundle show actionpack bundle show sprockets 

Используйте свой редактор, чтобы открыть каждую из этих библиотек, чтобы вы могли следить за исходным кодом.

Стандартный способ вставки тега JavaScript в Rails:

 <%= javascript_include_tag "application.js" %> 

Начиная с Rails 3.1, стандартный файл application.js может выглядеть так:

 //= require jquery //= require jquery_ujs //= require_tree . 

Разработчики Rails знают, что они могут определять зависимости любого файла JavaScript, используя специальный синтаксис Sprockets, и добавляемые дополнительные файлы фактически являются зависимостями application.js .

javascript_include_tag является определенным здесь помощником Rails. Помощники по умолчанию для Rails определены в actionpack/lib/action_view/helpers и javascript_include_tag является исключением. Но этот метод может только добавлять теги сценария к ответу HTML и не может интеллектуально анализировать файлы для разрешения зависимостей. Разрешение зависимостей активов обрабатывается Sprockets.

Sprockets настраивается в соответствии со средой Rails в actionpack/lib/sprockets/railtie.rb . Railtie является ядром платформы Rails и предоставляет несколько хуков для расширения Rails и / или изменения процесса инициализации. Если мы хотим изменить поведение Rails в любой момент во время или после процесса инициализации, мы можем использовать Railtie .

Sprockets расширяет поведение Rails, включая модуль Sprockets::Helpers::RailsHelper после action_view . Это означает, что вновь добавленный модуль переопределит методы с тем же именем, которые уже определены в модулях в action_view .

Теперь пришло время для небольшого эксперимента. Создайте новое приложение Rails с контроллером и установите его маршрут.

 # creates a new rails application rails new rails_asset_serve # navigate to newly created rails directory cd rails_asset_serve # create a new controller named test with one method index rails generate controller test index 

Идите вперед, отредактируйте app/views/test/index.html.erb и добавьте туда несколько фиктивных текстов. Теперь отредактируйте config/routes.rb и добавьте следующую строку, чтобы test контроллер был доступен из браузера.

 root :to => 'test#index' 

Запустите сервер Rails, перейдите к localhost:3000 , и вы увидите желаемый результат. Тем не менее, наша достопримечательность является источником этой страницы. Просмотрите исходный код, и вы увидите следующие теги JavaScript, включенные в ваш ответ HTML.

 <script src="/assets/jquery.js?body=1" type="text/javascript"></script> <script src="/assets/jquery_ujs.js?body=1" type="text/javascript"></script> <script src="/assets/test.js?body=1" type="text/javascript"></script> <script src="/assets/application.js?body=1" type="text/javascript"></script> 

Эти файлы JavaScript являются зависимостями application.js , как упоминалось выше. Теперь самое интересное. Закомментируйте actionpack/lib/sprockets/railtie.rb:46 и перезапустите ваш сервер.

На этот раз, когда вы заходите на страницу, вы не увидите никакой разницы в выводе, если не посмотрите на источник. Здесь обратите внимание, что есть только один тег JavaScript, указывающий на application.js . Это связано с тем, что помощник Rails по умолчанию не интеллектуален и, следовательно, имеет пропущенные зависимости. Sprockets достаточно умен, чтобы разрешать зависимости, что приводит к ссылкам на все наши исходные файлы JS.

Давайте посмотрим, как Sprockets выполняет эту магию.

Не забудьте раскомментировать actionpack/lib/sprockets/railtie.rb:46

Путешествие начинается

Давайте возьмем application.js в качестве примера. В actionpack/lib/sprockets/helpers/rails_helper.rb в line:7 вы можете видеть, что модуль Sprockets::Helpers::RailsHelper модуль ActionView::Helpers::AssetTagHelper . ActionView::Helpers::AssetTagHelper — это основной модуль, содержащий стандартные помощники Rails. Включая их в свой собственный модуль, Sprockets гарантирует, что у него все еще есть доступ ко всем помощникам Rails по умолчанию.

В line:20 вы можете увидеть, что javascript_include_tag определен. Этот метод вызывается, когда мы хотим включить актив JavaScript. В line:26 есть collect перечислитель, который возвращает массив разделенных тегов скрипта. В нашем случае sources будут указывать на application.js .

На line:27 вы можете увидеть оператор if . Если мы находимся в среде development тогда debug оценивается как true . Другая часть ( asset = asset_paths.asset_for(source, 'js') ) немного интересна. Если вы прочитали те две рекомендованные статьи, о которых я упоминал выше, то вы легко поймете, что происходит.

assets_paths — это метод, определенный в line:9 который возвращает экземпляр класса AssetPaths определенный в line:117 . В этом методе есть несколько назначений, но интересующее нас — line:12 .

asset_environment — это метод, результат которого присваивается paths.asset_environment . asset_environment определяется в line:113 . Этот метод возвращает Rails.application.assets который является экземпляром Sprockets::Environment , класса верхнего уровня, отвечающего за все, что связано с активами в Sprockets.

asset_for , в line:122 , это метод экземпляра, который вызывается для получения желаемого актива. asset_environment[source][/source] отвечает за возврат экземпляра Sprockets::BundledAsset который указывает на желаемый актив ( application.js в нашем примере). [] является сокращением для метода find_asset и определяется здесь .

asset_environment возвращает экземпляр Sprockets::BundledAsset содержащий все зависимости нашего актива. Перебор этих зависимостей выполняется с to_a метода to_a , так же как Sprockets делает в line:28 .

В line:29 есть вызов super , который является помощником Rails по умолчанию. Да, это так. Звездочки сделали несколько умных вещей. Во-первых, он включил свой модуль, когда загружается action_view приводит к переопределению этих методов. Затем он включил стандартные помощники Rails в свои собственные модули. Вызывая super в javascript_include_tag , он вызывает javascript_include_tag из помощников Rails по умолчанию. Стандартный помощник javascript_include_tag способен добавлять теги сценариев для источников, поэтому в line:29 мы вызываем его и передаем необходимую информацию и вуаля! Тег скрипта для каждой зависимости application.js вставляется.

Подводя итоги этого процесса, Sprockets сначала переопределяет стандартные помощники Rails, интеллектуально разрешает зависимости активов, а затем снова вызывает переопределенные методы для завершения своей работы.

Вы можете подумать, что разрешение активов выполняется при каждом обращении к нашему приложению Rails, но это не так. Когда мы запускаем / перезапускаем сервер Rails, все разрешение ресурсов происходит при первом вызове этих активов. Активы кэшируются и повторно используются при последующих вызовах, пока активы не будут изменены.

В production среде этот процесс прост. Давайте вернемся к line:20 , где определен javascript_include_tag .

Когда мы находимся в production среде, оператор if on line:27 оценивается как ложный, потому что debug ложная. Случай else ( line:31 будет выполнен и вызовет super , передав соответствующие значения. В production вставляется только один тег актива, поскольку все его зависимости объединяются в один файл с помощью Sprockets (когда мы запускаем rake assets:precompile ) ,

Процесс вставки тегов ресурсов таблицы стилей такой же, как и в JavaScript. Включение других тегов активов, таких как изображение, шрифт, аудио и т. Д., Довольно просто. В стандартных помощниках Rails пути к этим ресурсам были добавлены с соответствующим каталогом (изображения для изображения, аудио для аудио, шрифты для шрифта). Но в Sprockets эта штука заменяется одним методом, который добавляет все пути к активам с помощью Rails.application.config.assets.prefix (по умолчанию это / assets), который определен здесь . Все мы знаем, что каждый актив в приложении Rails, использующем Sprockets имеет этот формат /assets/__asset_name__ . В line:94 есть метод asset_prefix который возвращает Rails.application.config.assets.prefix .

Заворачивать

Мы видели, как Sprockets выполняет свою магию для разрешения зависимостей и вставки соответствующих тегов ресурсов. В следующей статье мы ответим на два оставшихся пункта, упомянутых в начале этой статьи. А пока иди и скажи всем своим друзьям, что ты освоил звездочки и теги активов!