Глава 7. Достойное выступление с JavaScript
Содержание
Мы живём в эпоху возрождения JavaScript - это уже далеко не мальчик для битья любителей чистоты языков
программирования. Rails внедрил современные технологии JavaScript, такие как React благодаря включению
Webpacker
: некого gem, привнёсшего поддержку
webpack
.
Будучи разработчиком Rails, важно иметь возможность сочетать эти технологии с вашими приложениями по мере необходимости, следовательно наша среда Docker должна поддерживать нс в этом предприятии.
В данной главе мы изучим возможность для работы с JavaScript в качестве части нашей разработки Rails. Мы также
увидим как включать интерфейс React в своё приложение Rails устанавливая и настраивая
Webpacker
.
К концу этой главы наша среда разработки на основе Docker засверкает новыми гранями при помощи таких современных новшеств JavaScript.
Когда дело доходит до сочетания JavaScript с интерфейсом для вашего приложения Rails, существует большое число различных вариантов. Вероятно самый крупный выбор это то будет ли ваше приложение Rails обслуживать интерфейс или нет. Оба варианта в полной мере рабочие, причём каждый из них имеет свои преимущества и недостатки и приводит к различным настройкам.
Если ваше приложение Rails не обслуживает ваш интерфейс, это означает что вы применяете своё приложение Rails в качестве некого уровня API. В этом случае у вас имеется отдельный интерфейс, обычно целиком написанный на JavaScript, каком- то из React, Ember, Vue.js или чего- то ещё. Такой подход выходит за рамки данной книги, так как он вовлечён в получение в вашей настройке очень специфичного JavaScript. Однако касательно основных понятий всё достаточно прямолинейно и вы в целом будете применять те навыки, которые вы уже изучили.
Вот общая схема:
-
Переименуйте свою службу
web
. Название важно. При данном подходе ваши приложения Rails в действительности это API или серверная часть, поэтому вам следует называть его так. -
Создайте некий индивидуальный образ для исполнения своего приложения интерфейса JavfScript. Для своего JS интерфейса вам следует сделать то же самое и так же как мы это делали когда создавали некий персональный образ для исполнения своего приложения Rails. Его
Dockerfile
может собираться поверх стандартного образа Node.js, добавляя по мере необходимости специфичные для приложения настройки. . -
В своём
docker-compose.yml
создайте обособленную службу интерфейса. Это будет обособленное приложение JavaScript. Через переменные среды вы будете настраивать конкретную оконечную точку API, которую она должна применять (имя домена и порт соответствующего API Rails).
С другой стороны, если вы применяете Rails для обслуживания своего интерфейса, это означает применение тех
функциональностей, которые предоставляет Rails. Для обслуживания интерфейса JavaScript Rails предлагает два механизма:
(основанный на Sprockets) конвейер ресурсов или новый подход Webpacker
,
добавленный в Rails 5.1.
Обычный конвейер ресурсов на основе Sprockets работает сразу после установки без какой бы то ни было особой настройки. Будучи частью самого исполняемого сервера Rails ваши ресурсы автоматически будут компилироваться и обслуживать ваши представления стандартным для Rails образом. Некий пример этого мы рассмотрим в своей следующей Главе 8, Проверка в среде Docker.
Получение же вашего приложения Rails работающим с Webpacker
требует некоторой
дополнительной настройки в Docker. Поскольку это настолько популярный подход, мы намерены предоставить вам руководство
его настройки в оставшейся части данной главы.
При помощи gem с названием webpacker
Rails имеет в своём составе некий способ
для построения богатых интерфейсов JavaScript в ваших приложениях начиная с версии 5.1.
Webpacker
имеет модульную архитектуру, которая позволяет вам интегрировать
различные технологии, такие как React, Ember, Vue.js или даже Elm.
Применяя в качестве примера React, давайте рассмотрим как бы нам пришлось настраивать Webpacker
в своём приложении в Docker.
Перво- наперво, Webpacker
требует Yarn и текущей версии Node. Это потребует некого
обновления для нашего образа Docker:
1: FROM ruby:2.6
- LABEL maintainer="rob@DockerForRailsDevelopers.com"
-
- # Включаем работу apt с источниками на основе https
5: RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends \
- apt-transport-https
-
- # Обеспечиваем установку современной версии Node
- # См. https://github.com/yarnpkg/yarn/issues/2888
10: RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -
-
- # Гарантируем самые последние пакеты для Yarn
- RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
- RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | \
15: tee /etc/apt/sources.list.d/yarn.list
-
- # Устанавливаем пакеты
- RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends \
- nodejs \
20: yarn
-
- COPY Gemfile* /usr/src/app/
- WORKDIR /usr/src/app
- RUN bundle install
25:
- COPY . /usr/src/app/
-
- CMD ["bin/rails", "s", "-b", "0.0.0.0"]
Для установки современной версии Yarn нам придётся добавить репозиторий пакета Debian Yarn в список источников (строки 13- 15).
Однако поскольку репозиторий пакета Yarn применяет HTTPS, нам приходится установить и пакет
apt-transport-https
(строки 5-6) что позволить его работу.
К несчастью существует проблема зависимости между Yarn и той (старой) версией Node.js, которая устанавливается по умолчанию. В строке 10 мы решаем это добавляя репозиторий пакета Node в свой перечень источников; это обеспечит нам установку более современной версии Node.
Наконец, в строке 20 мы добавили yarn
в перечень устанавливаемых нами пакетов.
Имея установленными yarn
и некую современную версию Node, мы теперь готовы настраивать
своё приложение на применение Webpacker
.
Если бы мы знали о том что собираемся применять Webpacker
при первом создании
своего приложения, мы бы могли включить поддержку с помощью параметра
--webpack
- например:
$ rails new myapp --webpack=react <other options>
Такой параметр --webpack=react
сгенерировал бы поддержку React нашего приложения
сразу при установке. Тем не менее, имея своё приложение уже созданным, добавление поддержки
Webpacker
потребует пары этапов, выполняемых вручную.
Вначале нам придётся обновить свой Gemfile
чтобы он содержал
Webpacker
:
gem 'webpacker', '~> 3.5'
Затем мы запускаем bundle install
через повторную сборку своего образа:
$ docker-compose build web
Давайте остановим свою службу web
, потому как она в настоящее время исполняет
нашу старую версию без установленного gem Webpacker
:
$ docker-compose stop web
Теперь мы можем установить в своём приложении Webpacker
:
$ docker-compose run web bin/rails webpacker:install
Ошибка переполнения inotify | |
---|---|
К сожалению, при исполнении нашей предыдущей команды вы можете столкнуться со следующим сообщением об ошибке, которое
появляется в результате ошибки в
gem
Хотя это и кажется неаккуратным, похоже что оно не оказывает какого- либо существенного воздействия и вы спокойно можете его игнорировать. |
с последующей интеграцией необходимого React Webpacker
:
$ docker-compose run web bin/rails webpacker:install:react
Хорошо, наше приложение настроено под Webpacker
и React. Тем не менее, прежде чем
мы сможем на самом деле сказать что мы всё сделали, нам требуется некий путь компиляции наших ресурсов React
автоматически.
Выступая в качестве части Webpacker
, Rails предоставляет двоичный файл
webpack-dev-server
. Это небольшой сервер, который работает в фоновом режиме,
автоматически вырабатывая наши управляемые webpack-
файлы.
Если бы вы вели разработку локально, это была бы просто другая команда, которую вы бы вызывали в своём терминале. Однако метод Docker состоит в исполнении этого в некоторой обособленной службе в её собственном контейнере.
Давайте добавим некую новую службу для этого в свой файл docker-compose.yml
:
1: version: '3'
-
- services:
- web:
5: build: .
- ports:
- - "3000:3000"
- volumes:
- - .:/usr/src/app
10: env_file:
- - .env/development/web
- - .env/development/database
- environment:
- - WEBPACKER_DEV_SERVER_HOST=webpack_dev_server
15:
- webpack_dev_server:
- build: .
- command: ./bin/webpack-dev-server
- ports:
20: - 3035:3035
- volumes:
- - .:/usr/src/app
- env_file:
- - .env/development/web
25: - .env/development/database
- environment:
- - WEBPACKER_DEV_SERVER_HOST=0.0.0.0
-
- redis:
30: image: redis
-
- database:
- image: postgres
- env_file:
35: - .env/development/database
- volumes:
- - db_data:/var/lib/postgresql/data
-
- volumes:
40: db_data:
Rails webpack_dev_server
разработан для работы в самом корне вашего приложения
Rails; именно по этой причине мы выполняем сборку из того же самого Dockerfile
(строка 17), что и нашу службу web
.
Хотя она и применяет те же самые образ и код, мы запускаем нашу новую службу другой командой. Вместо запуска своего
сервера Rails мы исполняем саму команду ./bin/webpack_dev_server
(строка 18).
Мы выставляем свою службу webpack-dev-server
по порту со значением по умолчанию
3035
(строка 20).
Мы бы хотели, чтобы наша webpack-dev-server
автоматически подцепляла и повторно
компилировала бы наши изменения по мере того как мы локально выполняем разработку без необходимости перезапуска.
Именно по этой причине в строке 22, как и в случае с нашей службой web
мы монтируем свои локальные файлы в этот контейнер.
Сама команда webpacker-dev-server
ожидает своего исполнения с теми же самыми
настройками что и наше приложение Rails. К счастью, имея эти файлы извлечёнными, мы можем просто повторно воспользоваться теми
же самыми env_file
(строки 23- 25).
Однако для обеспечения того чтобы webpacker-dev-server
отвечал на запросы с любого IP
адреса мы устанавливаем WEBPACKER_DEV_SERVER_HOST
в значение
0.0.0.0
(строка 27), во многом аналогично тому как мы поступали со своим сервером
Rails.
Получив настроенной нашу службу webpack_dev_server
, нам также требуется
настроить некую переменную среды Rails для своей службы web
с тем,
чтобы она знала где искать эту webpacker-dev-server
(строка 14).
Теперь нам требуется запустить свою службу web
для применения нашего нового
образа и подхвата этих новых изменений настроек:
$ docker-compose up -d web
а затем запустить нашу новую службу:
$ docker-compose up -d webpack_dev_server
теперь нашей целью является проверка того что мы можем настраивать своё применяющее Docker приложение Rails чтобы позволять нам разрабатывать современные приложения JavaScript с применением таких технологий как React. Чтобы покончить с этим, нам просто нужно показать как компилируется и корректно загружается с нашей настройкой некое простейшее приложение React.
Когда мы установили Webpacker
, он добавил некий пример приложения React
"Hello World" в app/javascript/packs/hello_react.jsx
,
которое строит некий <div>
, выводящий "Hello React!":
import React from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'
const Hello = props => (
<div>Hello {props.name}!</div>
)
Hello.defaultProps = {
name: 'World'
}
Hello.propTypes = {
name: PropTypes.string
}
document.addEventListener('DOMContentLoaded', () => {
ReactDOM.render(
<Hello name="React" />,
document.body.appendChild(document.createElement('div')),
)
})
Мы намерены воспользоваться этим приложением для проверки правильности установок Webpacker
:
Прежде всего нам требуется сгенерировать некую страницу, которая будет загружать это приложение React:
$ docker-compose exec web bin/rails g controller pages home
create app/controllers/pages_controller.rb
route get 'pages/home'
invoke erb
create app/views/pages
create app/views/pages/home.html.erb
invoke helper
create app/helpers/pages_helper.rb
invoke assets
invoke coffee
create app/assets/javascripts/pages.coffee
invoke scss
create app/assets/stylesheets/pages.scss
Давайте изменим наше выработанное представление (app/views/pages/home.html.erb
)
для загрузки имеющегося приложения React; когда мы будем там, давайте удалим содержимое по умолчанию и зададим новый
заголовок страницы:
<%= javascript_pack_tag 'hello_react' %>
<h1>React App</h1>
Хорошо, давайте посмотрим его вывод. Перейдите в http://localhost:3000/pages/home
и вы должны обнаружить содержимое "Hello React!" отображаемым в данной странице. Это подтверждает что
наше приложение React было правильно скомпилировано и загружено.
Автоматическое обновление также работает. Измените app/javascript/packs/hello_react.jsx
для установки значения defaultProps.name
на ваше имя:
<%= javascript_pack_tag 'hello_react' %>
<Hello name="<Your name>" />
Теперь, когда вы перезагрузите свой браузер, вы должны обнаружить обновление данной страницы (только если ваше имя, по случаю, не "React").
Это приложение не поражает воображение. Но имея эту основу вы теперь способны выполнять в своих приложениях Rails разработку при помощи React и строить всё что только пожелаете.
Ну всё - мы наконец сделали это. Теперь у нас имеется полноценной приложение Rails, работающее с Docker, которое целиком управляется через Compose. Красота, не так ли? Давайте быстро повторим то что мы прошли в этой главе:
-
Мы установили Yarn и современную версию Node в соответствии с требованиями
Webpacker
. -
Мы установили необходимый gem
Webpacker
. -
Мы добавили некую новую службу в свой файл
docker-compose.yml
который запускает нашуwebpack_dev_server
для автоматической компиляции ресурсов JavaScriptWebpacker
. -
Для проверки того что всё что мы правильно настроили для компиляции и запуска приложения React мы создали некое приложение Hello World React.
Теперь когда наше приложение поднято и запущено во всём его цвете, далее мы переключим ваше внимание на установку и запуск наших проверок в среде Docker.