8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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.jsrails-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の)トランパイルの対象ではなくなります。

追記

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

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

Webpacker 5.x -> jsbundling-rails

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

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

(オマケ) turbo-links -> turbo

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

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

(オマケ) Webpack -> Vite/esbuild etc

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

esbuild は goで書かれていて、高速に動作します。

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

Vite は、jsbundling-rails ではサポートされていませんが、vite_rails gemを利用すれば、railsに導入できます。

Rails系のフロントエンド開発では、Webpack からVite/esbuild への移行が進んでいます。

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

esbuild は 高速ではあるものの、アセット最適化に制限があるため、パフォーマンス上必要なアセット最適化がesbuildの機能では必要十分に行えないプロジェクトには向いていません。
(esbuildのコード分割はWIPな(開発途上の)機能です。)

そのようなプロジェクトでは、Viteへの移行(Viteの採用)をオススメします。

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

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

Vite/esbuild への移行が難しい場合には、Webpackとの互換性の高い Rspack への移行も視野に入ってきます。

Vite/esbuild 及び そのプラグイン? でオルタナティブの提供されていないwebpack の loader? を利用していて、webpack → Vite/esbuild できない場合でも、Rspackならオルタナティブ(のloader?)が提供されている可能性が高いです。

Webpack + esbuild-loader より Rspackのほうがビルド速度が高速です。

推敲中...

8
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
8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?