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
выполняет свою магию для разрешения зависимостей и вставки соответствующих тегов ресурсов. В следующей статье мы ответим на два оставшихся пункта, упомянутых в начале этой статьи. А пока иди и скажи всем своим друзьям, что ты освоил звездочки и теги активов!