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

Легкий! Я просто открою application.js и…

Подождите, файл манифеста? звездочки? Комментарий, в котором говорится, что здесь не рекомендуется помещать код? И эти строки выглядят так, как будто они закомментированы, но кажутся важными:

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

Я быстро понял, что здесь работает еще какая-то магия Rails. Я знаю, как писать JavaScript, но мне нужно научиться делать это на Rails.

Конвейер ресурсов

Rails будет автоматически управлять вашим кодом на стороне клиента, используя конвейер ресурсов. Это сделает несколько вещей для повышения производительности:

  • Минимизируйте файлы, чтобы уменьшить размер.
  • Объедините соответствующие файлы JavaScript и CSS в один файл. Это уменьшает количество файлов, которые необходимо обслуживать.
  • Файлы предварительной обработки должны быть скомпилированы в JavaScript или CSS. Вы можете использовать CoffeeScript и Sass прямо из коробки с Rails.
  • Примените «отпечаток пальца» к полученному файлу. Уникальный токен добавляется к имени файла каждый раз при изменении одного из этих файлов. Если с момента последнего развертывания приложения ничего не изменилось, имя файла останется прежним, и браузер будет использовать кэшированную версию файла.

Звездочки

Вся эта работа организована жемчужиной под названием Sprockets. Наш файл application.js на самом деле является файлом манифеста, который сообщает Sprockets, какие файлы мы хотим включить. Строки, которые выглядят как комментарии, на самом деле называются директивами. Директивы начинаются с //= и будут ссылаться на файл относительно файла манифеста. Расширение можно не указывать. Порядок, в котором написаны эти директивы, важен, поэтому любой файл, который является зависимостью, должен быть включен первым. Например, jquery пишется перед jquery_ujs. Оператор require_tree . означает, что все файлы в каталоге, включая папки, будут включены рекурсивно.

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

Тестирование

Давайте создадим файл с именем test.js в каталоге javascripts и добавим быстрое оповещение. Поскольку все файлы в каталоге уже необходимы, добавлять новую директиву не нужно.

alert('Hello from the application.js manifest file!');

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

<script src="/assets/application-d582e41b00bd9c7cfac35e44a6102471.js"></script>

Для всего сайта и для конкретной страницы

Файл манифеста application.js по умолчанию загружается в наш основной файл макета. Это имеет смысл для кода, который является зависимым, например, JQuery или некоторых простых скриптов. Это заставило меня задуматься: есть ли смысл загружать сюда сразу весь интерфейсный код? Что, если бы приложению сначала нужно было выполнить несколько шагов, например, зарегистрироваться, прежде чем мы доберемся до более крупного внешнего раздела? Не имеет смысла доставлять сюда все сразу. Должен быть способ создать еще один файл манифеста и включить его в отдельное представление, сохранив при этом все преимущества конвейера активов. К счастью, Sprockets позволяет легко это сделать.

Несколько файлов манифеста

Допустим, у нас есть приложение для блога с контроллером Posts, и мы хотим выполнить некоторый JavaScript только тогда, когда мы попадаем в представление для действия show.

Здесь нам нужно сделать несколько шагов по хозяйству:

  • Сначала создайте новый файл манифеста с именем posts_show.js.
  • Добавьте новую папку с именем sitewide. Любой JavaScript, который мы хотим сделать доступным для всего приложения, будет находиться здесь. Переместите test.js в эту папку.
  • Удалите оператор require_tree . из application.js. Поскольку мы разбиваем все на разные файлы манифеста, мы не хотим, чтобы все было включено сюда.
  • Добавьте новую директиву //= require_directory ./sitewide в application.js. (обратите внимание на относительный путь при использовании этой директивы).
  • Чтобы наш новый файл манифеста заработал, он должен включать директиву. В нашем случае мы сделаем posts_show файлом манифеста, добавив директиву //= require_self. Теперь мы можем записать наш код в этот файл.

Теперь наш каталог должен выглядеть так:

javascripts/
  +application.js
  +posts_show.js
  sitewide/
   +test.js

Последний шаг — сообщить Rails, что нам нужно предварительно скомпилировать другой файл помимо application.js. Это можно сделать в production.rb, закомментировав эту строку и добавив ссылку на наш новый файл.

config.assets.precompile += %w(posts_show.js)

Давайте добавим быстрое оповещение к posts_show.js, чтобы мы знали, что все подключено правильно:

alert('Hello from the posts_show manifest file!');

Включение нового файла манифеста

Самый простой способ включить наш новый файл — использовать помощники javascript_include_tag и content_for. Мы добавим этот блок кода в posts/show.html.erb:

<% content_for :head do %>
    <%= javascript_include_tag "posts_show" %>
<% end %>

Также не забудьте добавить это в раздел заголовка файла application.html.erb:

<%= yield(:head) %>

Эта строка должна идти после первой javascript_include_tag, которая ссылается на application.js. Это гарантирует, что для любой конкретной страницы JavaScript, которую мы напишем, будут загружены правильные зависимости.

При повторном запуске приложения предупреждение от application.js приходит первым. Перейдите к определенному сообщению, и мы получим новое оповещение!

Проверяя тег head нашего этого представления в рабочей среде, мы видим, что теперь есть два тега script, подтверждающие, что у нас есть два обработанных файла манифеста:

<script src="/assets/application-d582e41b00bd9c7cfac35e44a6102471.js"></script>
<script src="/assets/posts_show-404c9ef56a2fd0a6954b15593763385e.js"></script>

Поначалу Asset Pipeline может показаться немного запутанным, но Sprockets позволяет очень легко начать писать JavaScript. Используя директивы, вы можете организовать наш код так, как пожелаете. Хотя это и не всегда необходимо, разделение нескольких файлов манифеста является хорошим решением для добавления некоторого кода, специфичного для страницы, при этом в полной мере используются возможности Rails.