LoginSignup
7
4

Webpacker 3.x -> 5.x-> jsbundling-rails

Last updated at Posted at 2020-12-27

はじめに

※この文章はベータ版です。

既存のプロジェクトで Rails5.2 + Webpacker 3.5.5 ->
Rails6.1 + Webpacker5.2.1 -> Rails6.1 + jsbundling-rails
(-> Rails7.0 + jsbundling-rails)したので、手順etc を
メモしておきます。

(Rais6 -> Rails 7 する際には、Webpacker -> jsbundling-rails、
turbo-links -> turbo など、Rails7 からの正式採用なものの
Rails6 でも動作する gem への移行、Rails6 では動作するものの Rails7
以降への対応が怪しい gem の Rails7対応済/対応中の gemへの移行、
例:Refile -> Shrine、をインクリメンタルに行なってから、
Rails6 -> Rails7 することをオススメします。
)

Rails5.2 -> Rails6.1

プロジェクトの rails & Webpacker gem を更新する

プロジェクトのルート・パスに移動後、gems.rb(Gemfile) を編集し、
バンドルされた gem を更新します。

% vim gems.rb
gem 'rails', '~> 6.1.0'
gem 'webpacker', '~> 5.2.1'
% bundle update

表示されるメッセージで gem の依存関係を確認し、依存関係に問題が
なくなるように gems.rb(Gemfile) を編集し、bundle update
実行します。この作業をエラーが出なくなるまで繰り返します。

アップデートタスクを実行する

% bundle exec rails app:update

プロジェクトをGit etcでリポジトリでバージョン管理していない場合には
バックアップをとってから実行します。

実行により、いくつかのファイルのコンフリクトが指摘され、上書きするか
どうか訊いてきますが、全て、上書きします。

上書きされたファイルとリポジトリ上(or バックアップ)にある対応する
ファイルの差分をチェックし、上書きされたファイルに必要な記述を復元
します。

Webpacker 3.5.5 -> 5.2.1

% bundle exec rails webpacker:install

実行により、いくつかのファイルのコンフリクトが指摘され、上書きするか
どうか訊いてきますが、全て、上書きします。

上書きされたファイルとリポジトリ上(or バックアップ)にある対応する
ファイルの差分をチェックし、上書きされたファイルに必要な記述を復元
します。

Vue.js まわりのアップデート (オプション)

% bundle exec rails webpacker:install:vue

他のフレームワークを利用している場合には、対応した
タスクがあれば、それを実行します、対応したタスクがない
場合には自前で更新します。

babel-loader の設定変更 (オプション)

Vue.jsでHTMLテンプレートのコンパイルをブラウザでの実行に行う場合
にはconfig/webpack/environment.js に次の設定のどちらかを追加します。

// Vue.js フル版(Compiler入り)
environment.config.resolve.alias = { 'vue$': 'vue/dist/vue.esm.js' } // Vue2
environment.config.resolve.alias = { 'vue$': 'vue/dist/vue.esm-bundler.js' } // Vue3

この設定がないときは、コンパイラなしの
vue/dist/vue.runtime.esm.js (Vue2) / vue.runtime.esm-bundler.js (Vue3)
が、読み込まれます。
(Vue.jsでHTMLテンプレートの実行時コンパイルを行なっている場合、
エラーになります。)

rails-erb-loaderのアップデート (オプション)

% bundle exec rails webpacker:install:erb

node_modules の更新

% yarn install

表示されるメッセージで NPM モジュールの依存関係を確認し、必要な NPM モジュールが
あればyarn add でインストールしてから、再度、yarn install を実行
します。この手順をエラーが出なくなるまで繰り返します。

.babelrc の削除

Webpackerの3.xでは必要でしたが、Webpacker4.x 以降では、babel.cofig.jspostcss.config.js.postcssrc.yml
に置き換わっているので、削除します。

バンドル

% bin/webpack

動作確認

% bundle exec rails s

rails-ujs -> @rails/ujs (オプション)

% yarn add @rails/ujs

Sprocketsを利用している場合は、
app/assets/javascripts/application.js
rails-ujs@rails/ujsに変更します。

//= require @rails/ujs

Webpackerを利用しているorする場合は、app/javascript/packs/application.js
に、次の2行を追加します。

import Rails from '@rails/ujs';
Rails.start();

Webpackerでの管理に新規に移行する場合には、erbにある
javascript_include_tag 'application'
javascript_pack_tag 'application'
変更します。

WebPackerの 設定変更 (オプション)

SplitChunk の有効化 (オプション)

config/webpack/environment.js に次の設定を追加します。

environment.splitChunks()

erbにある javascriot_pack_tagjavascript_packs_with_chunks_tag
に変更します。

node_modules を babel-loader の対象から除外する(オプション)

config/webpack/environment.js に次の設定を追加します。

environment.loaders.delete('nodeModules')

Webpacker4.x以降では、デフォルトでは、node_modules
ディレクトリにあるファイルが babel-loader 経由での(Babelの)
トランパイルの対象になっています。

この追加により、Webpacker3と同様にWebpacker4以降でも
babel-loaderがnode_modulesディレクトリを無視する
挙動になります。

Webpacker4以降でブラウザで動作確認を行なった際に、node_modules
下にあるNPMモジュールでエラーが発生している場合、この設定変更を試すこと
をオススメします。

node_modules ディレクトリにあるファイルがbabel-loader経由
でのトランパイルの対象になっていることにより、思わぬ変換が行われている
ことが原因である可能性があります。

例えば、node_modules ディレクトリにあるバンドル対象のファイル内
module.exports =の記述がある場合、WebPacker4.x以降の
デフォルト設定では、

Cannot assign to read only property 'exports' of object

エラーが発生することがあります。

自作の NPMモジュールをnode_modulesディレクトリで管理していて
クライアントサイドから利用しているので Babel でのトランスパイルが
必要etc、の理由で、babel-loader のトランスパイル対象から
node_modulesディレクトリを外せない場合には、次のようにして、
エラーが発生している任意の NPM モジュールを babel-loader での
トランスパイルの対象から外すことができます。

const nodeModulesLoader = environment.loaders.get('nodeModules')
if (!Array.isArray(nodeModulesLoader.exclude)) {
  nodeModulesLoader.exclude = (nodeModulesLoader.exclude == null)
    ? []
    : [nodeModulesLoader.exclude]
}
nodeModulesLoader.exclude.push(/任意のNPMモジュール/)

追記

Webpackerは、6.0.0から、デフォルトでは、node_modules
ディレクトリにあるファイルは babel-loader 経由での(Babelの)
トランパイルの対象ではなくなります。
https://github.com/rails/webpacker/blob/master/CHANGELOG.md#600---2021-tbd
https://github.com/rails/webpacker/pull/2624

追記

Rails7.0 から、Webpacker が Rails 本体から分離され、改名、有志の手に
より Shakapacker として開発・メンテナンスされていくことになりました。

Shakapackerは、いつまで開発・メンテナンスされていくのか、Railsの
バージョンアップにどこまで追従されていくのか、不透明のため、一時的に
Webpacker -> Shakapacker するにしても、どこかの時点で、
jsbundling-rails への移行に踏み切るのが無難と思われます。
(継続的に機能追加・メンテナンスされていくWEBアプリの場合)

Webpacker 5.x -> jsbundling-rails

jsbundling-rails は Rails6.x に対応しています。

公式の手順通りにすれば、移行できます。

Rails: Webpacker→jsbundling-rails+webpackアップグレード手順(翻訳)
https://techracho.bpsinc.jp/hachi8833/2022_02_03/115289

(オマケ) turbo-links -> turbo

Turbo も Rails6.x に対応しています。

Rails UJS・Turbolinks -> Turboアップグレードガイド(翻訳)
https://techracho.bpsinc.jp/hachi8833/2022_01_25/115082

Turbo Frame / Turbo Stream を利用する場合、Stimulus との
併用が視野に入ってきます。(Hotwire)

(オマケ) webpack -> esbuild

jsbundling-rails では、フロントエンドのビルドツール
として、webpack だけでなく esbuild もサポートしています。

esbuild は goで書かれていて、高速に動作するので、これからの
Rails系のフロントエンド開発では、webpack から esbuild への
移行が急速に?進んでいくと思います。

(JSガッツリなフロントエンド開発では、Vite(esbuildを内部で利用)
or esbuild への移行が進んでいるようです。 )

esbuild への移行をオススメします。

Webpacker の話に戻すと、Webpacker -> jsbuilding-rails
で esbuild への移行をしたい場合でも、
Webpacker -> jsbuilding-rails + webpack ->
jsbuilding-rails + esbuild、 と、ワンクッション挟んでの
移行をオススメします。

jsbuilding-rails + webpack においても、esbuild-loader
を利用して、babel-loader を置き換えることで、esbuild に
移行した場合ほどではありませんが、ビルドを高速化できます。
(jsのトランスパイルを babel -> esbuild することで、ビルドを
高速化します。)

esbuild 及び そのプラグイン? でオルタナティブの提供されていない
webpack の loader を利用していて、webpack → esbuild できない
場合、esbuild-loader は有用です。

推敲中...

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4