Пятница, 09 сентября 2022 05:10

Миграция Webpacker - JSBundling-rails (webpack)

Оцените материал
(0 голосов)
Миграция Webpacker - JSBundling-rails (webpack)
Миграция Webpacker - JSBundling-rails (webpack).

 

Странно впечаталось в память: аккурат сразу после появления Webpacker - обертки ruby под webpack - в качестве компилятора JavaScript по умолчанию (Ruby on Rails 6, доступен начиная с RoR 5.2), в Сети появилось множество статей рубистов/рельсовиков (я читал, в основном, на английском), восторженно расхваливающих нововведение и разносящих на все корки Sprockets. Дескать, и тем были плохи звездочки, и этим; а вот Webpacker - да, реально вещь. Продержался webpacker недолго, на сегодняшний день реинкарнировав в Shakapacker: в седьмых рельсах на смену пришел JSBundling-rails, предоставляющий на выбор сразу несколько упаковщиков. А Sprockets, хм, по-прежнему неизменно активно присутствует в новых проектах Ruby on Rails.

Что интересно. Походу, те же самые (я образно) авторы, превозносившие в бытность Webpacker, сегодня дружно переключились в том же самом ключе на JSBundling-rails; довелось уже прочесть немало негатива и про Webpacker. Да, "ruby-разработчик не обязан быть фронтендером", npm и yarn не для него, веб-технологии развиваются несказанно быстро... все так. Но, возможно, сказывается недоверчивая ментальность жителя РФ, и именно всеобщие восторги вчера - вселяют лично в меня некоторые сомнения относительно прочности новых веяний сегодня. Впрочем, будем посмотреть. Что еще остается, особенно с учетом реалий дня? - только наблюдать.

Чуть забегая вперед - об одном небесполезном трюке. Итак, будь то Webpacker, Shakapacker или JSBundling-rails - ок; скажите, знаете ли вы, что даже в актуальном релизе Rails вы вполне можете по старинке использовать Sprockets в качестве компилятора js? Это не преподносится в качестве правильного "rails way", но в ряде случаев способно оказаться полезным: допустим, вы не умеете (или, может статься, лениво) переписать javascript таким образом, чтобы создание ES6-модуля на его основе оказалось возможным.

Ничто не может быть проще: создаем (название именно так, во множественном числе) каталог:

app/assets/javascripts

 

и добавляем

//= link_directory ../javascripts .js

 

в

app/assets/config/manifest.js

 

Остальное неизменно: javascript_include_tag, и вперед. Кратко и емко в контексте отличий Webpack от Sprockets - в статье by Younes Serraj. И какой нам, вообще говоря, right way после параллельного импорта! - гулять так гулять, стрелять так стрелять, один хрен счет будет неподъемным.


Это было, можно сказать, лирическое отступление, а теперь займемся собственно миграцией from Webpacker to JSBundling-rails (из духа противоречия я выбрал все тот же webpack). Рассказанное и показаное далее ни в коей мере не является чем-то эксклюзивным и инновационным, но содержит ряд практических деталей, способных в некоторой степени облегчить описываемый переход для новичков Ruby on Rails.

 

# Add to your Gemfile
+ gem 'jsbundling-rails'

# From the CLI, rebuild the bundle
./bin/bundle install

 

Раз уж webpack, стало быть, миграция начинается у меня (обновлял rails-blog) вот с таких команд в терминале:

./bin/rails javascript:install:webpack
mv webpack.config.js config/webpack

 

При необходимости и если что-то пойдет не так - не стесняйтесь взглянуть скрипты блога: репозиторий называется CRUD-Blog, это полностью рабочая демка, опубликованная на Heroku.

Увидеть на гитхабе.

 

Сообразно конфигурации своего web-приложения отредактируйте application.html.erb, никаких javascript_pack_tag, stylesheet_pack_tag там (и не только там) остаться не должно. Можно поискать для верности::

grep -Fre 'pack_tag' app

 У меня, например, вот так:

grep -Fre 'link_tag' app
app/views/layouts/application.html.erb:  <%= stylesheet_link_tag 'application', media: 'all' %>
app/views/layouts/application.html.erb:  <%= stylesheet_link_tag("clean-blog.min") %>
app/views/layouts/application.html.erb:  <%= favicon_link_tag 'favicon.ico' %>
app/views/contacts/index.html.erb:  <%= stylesheet_link_tag("contacts_only") %>
app/views/contacts/index.html.erb:  <%= stylesheet_link_tag("mdb") %>

 

Вносим изменения в два файла:

# webpack.config.js:
- path: path.resolve(__dirname, "app/assets/builds"),
+ path: path.resolve(__dirname, '..', '..', 'app/assets/builds')

# package.json
- "build": "webpack --config ./webpack.config.js"
+ "build": "webpack --config ./config/webpack/webpack.config.js"

 

Удаляем файлы и директории, "убедившись, что перенесли все внесенные в них настройки":

./bin/webpack
./bin/webpack-dev-server
./config/initializers/webpacker.rb
./config/webpacker.yml
./config/webpack/development.js
./config/webpack/environment.js
./config/webpack/production.js
./config/webpack/test.js

 

А вот здесь кофе-брейк и небольшая рекламная пауза...

 

 

Необходимо, по-видимому, остановиться на контексте директивы о переносе настроек, что почерпнута из перевода официальной доки миграции. Уточню, речь идет сугубо о конфигах, отличных от дефолтных, т. е. привнесенных вами ранее, в процессе разработки rails-app, изменениях. Для меня это был конфиг jQuery, установленного посредством yarn.

 

Чтобы "перенести настройки", порекомендую прислушаться к совету, прозвучавшему в лекции How to use jQuery & jQueryUI with Esbuild знаменитого Chris from GoRails: создать файл, содержащий всего три строчки:

add_jquery.js

import $ from 'jquery';
window.jQuery = $;
window.$ = $;

, и импортировать в application.js:

import "./add_jquery"

 

Иначе в консоли непременно получите Uncaught ReferenceError: $ is not defined или что-нибудь в этом роде.

 

Кстати. Чтобы ошибка исчезла (а jQuery заработал), только лишь перезапуска rails-сервера может не хватить: используйте

rake assets:clobber
rake assets:precompile

 

Но все это чуть позже, после окончания миграции. Которое уже (да, вот так быстро) не за горами.

Удаляем из двух конфигов:

config/initializers/assets.rb

-# Add Yarn node_modules folder to the asset load path.
-Rails.application.config.assets.paths << Rails.root.join('node_modules')

config/initializers/content_security_policy.rb

-#   # If you are using webpack-dev-server then specify webpack-dev-server host
-#   policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development?

 

Удаляем из Gemfile gem "webpacker", бундлим. Еще удаляем: 

yarn remove @rails/webpacker webpack-dev-server

 

Последний (во всяком случае, на это есть некоторая надежда) штрих. Смотрите, что в итоге получилось: у нас теперь есть новая точка входа app/javascript/application.js. Куда очень бы неплохо переместить содержание старой точки входа Webpacker, скопировав всё из app/javascript/packs - в app/javascript. Старый файл application.js смело копируйте с заменой нового, вновь созданного: он у вас пока что пустой. Озаботьтесь корректностью относительных путей на новом месте и, что немаловажно, полностью избавьтесь от require, заменив на import.

Пробуем:

yarn build --progress --color

 

Примечание. Если с этого места начинаются пляски с бубнами вокруг путей импорта - yarn снова и снова выдает ошибки - вы можете попытаться вернуть на место (временно) удаленную из config/initializers/assets.rb (см. выше) строчку. Либо же добавить аналогичную в config/application.rb:

config.assets.paths << Rails.root.join('node_modules')

 

Из потенциакльных проблем: Error message "DevTools failed to load SourceMap: Could not load content for chrome-extension://..." в консоли - не имеет отношения к вашему коду и элегантно отключается в настройках Chrome. ActionController::RoutingError (No route matches [GET] "/assets/application.js....) в Ruby on Rails 6 легко лечится: смените true на false в

config/environments/development.rb

config.assets.debug = true

 

Нужен ли вам babeljs - решайте сами. Я подумал... и забил на это дело. Если считаете иначе -

yarn add @babel/core @babel/preset-env babel-loader

 

, подробности на страничке официального дока jsbundling-rails.

Последнее изменение Понедельник, 26 сентября 2022 19:01

Оставить комментарий

Добавьте ваш комментарий

Комментарии в блоге

Заказать сайт

Веб-разработка. Заказать сайт

Вы можете заказать сайт-визитку, блог, корпоративный сайт, интернет-магазин или коммерческий web-портал.