Статьи

Как работает прекомпиляция активов, часть I

Абстрактные зубчатые колеса

Веб-приложения становятся все быстрее и быстрее с каждым днем. Одной из наиболее важных функций, позволяющих пользователям возвращаться, является скорость. Если веб-приложение работает медленно и требует слишком много времени для загрузки, оно потеряет своих пользователей. Если веб-приложение работает быстро, количество пользователей увеличится. Разработка медленного веб-приложения в настоящее время не вариант.

Существует множество факторов, влияющих на производительность веб-приложения, и важным является загрузка ресурсов, таких как изображения, файлы CSS, файлы JavaScript и т. Д. Каждое веб-приложение содержит несколько изображений и файлов CSS, чтобы он выглядел красиво, а также некоторые файлы JavaScript для работы с пользователем. взаимодействие и поведение. Если ресурсы загружаются быстрее, веб-приложение должно работать лучше. Существует множество стратегий для быстрой загрузки ресурсов, таких как минимизация, сжатие (gzipping), кэширование и т. Д.

Существует несколько платформ, которые имеют встроенную функциональность для выполнения вышеупомянутых операций с активами. Мы (сообщество Ruby) любим Rails и Rails имеет встроенную поддержку для выполнения различных операций с активами начиная с версии 3.1. Спасибо @sstephenson и @joshpeek за огромные усилия по разработке и поддержке Sprockets . Sprockets — это Ruby Gem, который позиционируется как «система упаковки активов на основе стоек». Sprockets можно использовать с любой веб-платформой на основе Rack, такой как Sinatra, Padrino и т. Д. Sprockets встроен в Rails 3.1 и считается неотъемлемой частью Rails.

Чтобы узнать о Sprockets, есть отличное руководство по Rails . Я рекомендую вам прочитать Руководство Rails по Sprockets, прежде чем приступить к этой статье. В этой статье мы рассмотрим, как работает конвейер активов в Rails, и как работает прекомпиляция активов.

рейк активы: прекомпиляция

Мы используем rake assets:precompile чтобы прекомпилировать наши активы перед тем, как отправлять код в производство. Эта команда прекомпилирует ресурсы и помещает их в каталог public/assets в нашем приложении Rails. Давайте начнем наше путешествие с рассмотрения внутренних возможностей Rails Asset Pipeline. Эта статья основана на Rails 3.2.15 и Sprocket 2.2.2 . Если вы еще не установили Rails 3.2.15 , сначала установите его.

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

Давайте сначала создадим тестовое приложение Rails. Мы будем использовать это приложение для просмотра и настройки различных параметров конфигурации, а также для просмотра наших предварительно скомпилированных ресурсов. Для создания приложения на Rails мы используем следующую команду:

 rails new asset_pipeline_test 

Вы можете использовать любое имя, которое вам нравится, вместо asset_pipeline_test . cd во вновь созданное приложение Rails и введите следующую команду, чтобы найти путь к каталогу гемов Rails (я предполагаю, что вы установили необходимые гемы, выполнив команду bundle install ).

 bundle show rails 

Эта команда вернет путь к каталогу гемов Rails. Выполните ту же команду, изменив rails на sprockets чтобы получить путь к каталогу гемов Sprockets.

Теперь у меня есть сюрприз для вас. Идите дальше и проверьте содержимое каталога Gem Sprockets, перейдя по пути от запуска этих команд. Вы увидите разные файлы в каталоге Gem Sprockets.

Теперь перейдите в каталог gem-ов Rails, и вы можете быть удивлены, что этот каталог пуст :-). Я был немного шокирован, увидев пустой каталог. Мы все знаем, что у каждого драгоценного камня есть каталог, и все его файлы находятся там. Если это правда, то где же Rails gem файлы ??? Rails 3 был основным рефакторингом, и теперь все гораздо более организовано по сравнению с Rails 2.x. railties-3.2.15 файлы Rails находятся в railties-3.2.15 поэтому вместо использования rails-3.2.15 мы будем использовать railties-3.2.15 для проверки различных частей Rails.

Также откройте actionpack-3.2.15 в вашем любимом редакторе, потому что у него есть каталог sprockets который содержит необходимый код для запуска Sprockets из Rails.

Звездочки :: Окружающая среда

Согласно Sprockets, нам нужен экземпляр класса Sprockets::Environment для доступа и обслуживания ресурсов из вашего приложения. Давайте посмотрим, где это определено в коде.

Вот код, отвечающий за создание экземпляра Sprockets::Environment для нашего приложения Rails. Вам может быть интересно, почему этот код находится в railtie.rb . Ответ на этот вопрос очень прост.

Как я упоминал ранее, Rails 3 был основным рефакторингом (спасибо основной команде Rails за их потрясающие усилия). Rails::Railtie является ядром платформы Rails и предоставляет несколько хуков для расширения Rails и / или изменения процесса инициализации. Railtie предоставляет нам несколько хуков для выполнения желаемой функциональности. Мы хотим, чтобы экземпляр Sprockets::Environment доступен для нашего приложения перед выполнением любого другого кода, поэтому мы расширяем наш класс Sprockets::Railtie из Rails::Railtie . В блоке кода в строке: 23 мы присваиваем экземпляр Sprocket::Environment для app.assets . app является экземпляром нашего приложения Rails, и вы знакомы с ним в форме Rails.application .

У нас есть две версии активов. app.assets и config.assets . config является экземпляром app.config который был назначен config в строке: 18 . config.assets в контексте Sprockets::Railtie или Rails.application.config.assets — это объект конфигурации, который используется для хранения различных параметров конфигурации для Rails.application.assets .

В обзоре Rails.application.assets является экземпляром Sprockets::Environment а Rails.application.config.assets является объектом конфигурации.

Rails.application.config.assets определяется здесь . Как видите, он содержит параметры конфигурации, которые мы используем для настройки различных сред из разных файлов из нашего приложения Rails.

Теперь мы знаем, где создается экземпляр Sprockets::Environment и в чем разница между Rails.application.assets и Rails.application.config.assets . Давайте глубоко погрузимся во внутренности звездочек.

Типы активов

Есть следующие три типа активов в соответствии со звездочками

  • Связанные активы
  • Обработанные активы
  • Статические активы

Статический Актив

Мы рассмотрим более подробно о связанных и Processed Assets в части 2. Здесь мы обсуждаем Static Assets . Статические активы — это активы, которые не нуждаются в дополнительной обработке. Они просто созданы с новым именем. Изображения, например, являются статическими активами. Давайте посмотрим, как статические ресурсы предварительно компилируются и сохраняются.

Перейдите сюда, и вы увидите метод build_asset . build_asset используется для создания ресурса (дух). logical_path — это имя ресурса, т.е. rails.png а pathname — что-то вроде /home/ubuntu/Desktop/work/asset_pipeline_article/app/assets/images/rails.png (ваш путь будет отличаться в зависимости от root вашего приложения).

В строке: 381 вы увидите следующую строку

 StaticAsset.new(index, logical_path, pathname) 

StaticAsset определяется в геме Sprockets в каталоге lib/sprockets . StaticAsset является подклассом Asset . Asset является базовым классом для всех типов активов.

Перейдите сюда, чтобы увидеть метод initialize для класса Asset . В методе build_asset мы видели, что создается экземпляр StaticAsset . Когда создается экземпляр StaticAsset вызывается метод initialize Asset . Для StaticAsset создается дайджест и сохраняется новый файл с новым именем, который содержит file_name-digest.file_ext . Дайджест создается на основе содержимого файла.

Здесь файл сохраняется. Этот метод отвечает за сохранение ресурсов на диск и довольно понятен.

Запустите rake assets:precompile из командной строки из корня вашего Rails-приложения. Посмотрите на каталог public/assets и вы увидите активы вашего Rails-приложения. На данный момент наш интерес представляет rails.png .

Обратите внимание, что существует две версии rails.png : одна с именем rails.png name и другая с именем rails-a3386665c05a2d82f711a4aaa72d247c.png . Вам может быть интересно, как создаются два файла, потому что, как вы видите в методе write_to только один параметр filename . Как Sprockets создает два файла? На этот вопрос ответят во второй части этой статьи.

Вам также может быть интересно, где и как создается этот digest . В конструкторе класса Asset вы увидите следующую строку:

 @digest = environment.file_digest(pathname).hexdigest 

environment — это экземпляр Index определенный в index.rb в index.rb Sprockets в index.rb lib/sprockets . Это подкласс Base определенный в base.rb в base.rb lib/sprockets base.rb . file_digest определяется в base.rb Перейдите к методу file_digest в base.rb и в строке 242 вызывается метод digest .

В методе digest вы можете видеть, что если @digest существует, он используется, и возвращается дублированная копия, или создается новый дайджест, и возвращается его дублированная версия. digest_class умолчанию digest_class возвращает Digest::MD5 . Однако мы можем назначить и другой класс, такой как Digest::SHA1 . Digest::MD5 присваивается digest_class здесь . Новый дайджест создается методом digest с использованием следующей строки:

 digest_class.new.update(VERSION).update(version.to_s) 

Здесь VERSION — это Sprockets::VERSION а version.to_s — это production-1.0 .

Основываясь на этой информации, давайте использовать нашу консоль, чтобы увидеть, сможем ли мы генерировать те же дайджесты, которые Sprockets генерирует для rails.png . Введите rails console в корне вашего приложения Rails.

Чтобы создать дайджест для rails.png , у нас должен быть путь к rails.png . Как уже упоминалось, путь является абсолютным путем актива. В моем случае путь к rails.png — это /home/ubuntu/Desktop/work/asset_pipeline_article/app/assets/images/rails.png .

Введите следующие команды в консоли:

 digest = Digest::MD5.new digest.update(Sprockets::VERSION).update('production-1.0') digest.file("/home/ubuntu/Desktop/work/asset_pipeline_article/app/assets/images/rails.png").hexdigest 

Метод digest.file возвращает дайджест для файла на основе его содержимого. В моем случае это даст нам a3386665c05a2d82f711a4aaa72d247c для rails.png , подтвердив тот же дайджест, что и Sprockets. Дайджест одинаков для rails.png по умолчанию во всех приложениях Rails, если Sprockets::VERSION и version.to_s одинаковы.

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

Я надеюсь, что вы узнали что-то о Asset Pipeline сегодня. Будьте внимательны к части 2 !