Rails: Webpacker v5からShakapacker v6へのアップグレードガイド(翻訳)
Shakapacker v6では、Webpacker 5からの移行に伴う大幅な変更点がいくつかあるため、手動での対応が必要です。本ガイドはそうした作業を支援するためのドキュメントです。
ShakaCodeはWebpackerからのアップグレードやShakapackerの利用をサポートします。ご興味のある方はjustin@shakacode.comまでお知らせください。
🔗 Webpacker/Shakapackerは「Webpackのスリムなラッパー」になった
デフォルトのWebpacker 6は、JavaScriptのコンパイルとバンドルに重点を置いています。これは、CSSや静的画像をSprocketsでトランスパイルするRailsの既存のアセットパイプラインと組み合わせる形になります。ほとんどの開発者にはこの組み合わせが推奨されますが、CSSや静的アセットもWebpackerで扱いたい場合は、READMEの『integrations』を参照してください。
以前のWebpacker は、webpackを間接的に設定する形を取っていたため、複雑な二次設定プロセスが発生していました。これは元々、人気の高いフレームワークのデフォルト設定を提供することが狙いでしたが、結果的には解決される問題よりも複雑さの方が増してしまいました。そのため現在のWebpackerは、すべての設定をwebpackのデフォルト設定に直接委譲しています。さらに、webpackやbabelなどの主要な依存関係は「ピア依存関係」になっているので、自由にアップグレードできます。
フレームワークとの統合は自分で設定する必要がありますが、webpack-merge
が役に立ちます。詳しくは本記事のv5からv6への移行例にあるVueの移行例を参照してください。
🔗 Webpacker v6.0.0.rc.6をShakapacker v6.0.0に移行する
移行例については、shakacode/react_on_rails_tutorial_with_ssr_and_hmr_fast_refreshの#27を参照してください。
🔗 v6.5.2に更新する
bin/webpacker
やbin/webpacker-dev-server
のバイナリスタブからNODE_ENV
の設定を削除してください(Webpackランナーファイルではこれらが設定されないので不要です)。
🔗 v6.0.0.rc.6からv6.0.0に更新する手順
注: Webpacker v5を利用している場合は、最初に後述の『Webpacker v5をv6.0.0.rc.6にアップグレードする』手順に沿ってv6.0.0.rc.6にアップグレードしておいてください。
- 1. gem名を
webpacker
からshakapacker
に変更し、NPMパッケージを@rails/webpacker
からshakapacker
に変更します。 -
2. 以下を実行して、ピア依存関係をインストールします。
yarn add @babel/core @babel/plugin-transform-runtime @babel/preset-env @babel/runtime babel-loader compression-webpack-plugin terser-webpack-plugin webpack webpack-assets-manifest webpack-cli webpack-merge webpack-sources webpack-dev-server
古いバージョンのライブラリがインストールされている可能性があります。yarn install
を実行して以下のような警告が出力されていないかどうかをチェックしてください。言い換えれば、このようなエラーは重大なものであり、対応しないと著しい混乱が生じます。
warning " > shakapacker@6.1.1" has incorrect peer dependency "compression-webpack-plugin@^9.0.0"
file-loader@1.1.11" has incorrect peer dependency "webpack@^2.0.0 || ^3.0.0 || ^4.0.0"
- 3.
bin/webpack
やbin/webpack-dev-server
を呼び出すスクリプトを更新して、それぞれbin/webpacker
やbin/webpacker-dev-server
に変更します。 -
4. webpack の設定を更新して、単一の設定ファイル
config/webpack/webpack.config.js
を作成します。以前のように
NODE_ENV
ごとに個別のファイルを使う方法にしたい場合は、config/webpack/webpack.config.js
で以下のshimを利用できます。
警告: 以前は、NODE_ENV
を設定しない場合のNODE_ENV
のデフォルトはdevelopment
でした。そのため、以前config/webpack/development.js
が実行されることを期待していた部分では、代わりに自分のRAILS_ENV
に対応するコンフィグファイルを使ってください。RAILS_ENV
がtest
の場合はconfig/webpack/test.js
が実行されます。
// このファイル名はconfig/webpack/webpack.config.jsにする
const { env, webpackConfig } = require('shakapacker')
const { existsSync } = require('fs')
const { resolve } = require('path')
const envSpecificConfig = () => {
const path = resolve(__dirname, `${env.nodeEnv}.js`)
if (existsSync(path)) {
console.log(`Loading ENV specific webpack configuration file ${path}`)
return require(path)
} else {
// NODE_ENV用のファイルが存在しないのは、おそらく誤り
throw new Error(`Got Error with NODE_ENV = ${env.nodeEnv}`);
}
}
module.exports = envSpecificConfig()
- 5. JSXのサポートが必要な場合は、
babel.config.js
を更新してください。詳しくはShakapackerの『Customizing Babel Config』ドキュメントを参照してください。 - 6.
asset_pack_path
ビューヘルパーを利用している場合は、パスに含まれる"media/"を"static/"に変更するか、image_pack_path
の利用を検討してください。
🔗 Webpacker v5をv6.0.0.rc.6にアップグレードする
- 1. gitで新しいブランチを作成し、そのブランチで作業するようにしてください。
このブランチですべてのファイルを上書きし、不要な変更を元に戻すことになります。
訳注
以下の記述は削除されました。
- 2. webpacker.ymlの以下の
source_entry_path
をv5のデフォルトから変更することを検討します。
source_path: app/javascript
source_entry_path: packs
上のv5のパスを、以下のようにv6に変更することを検討します。
source_path: app/javascript
source_entry_path: /
続いて、
app/javascript/packs/*
にあるファイル(application.js
も含む)をapp/javascript/
ディレクトリに移動してから設定ファイルを更新することも検討します。なお、このファイル移動は必須ではなくオプションなので、
packs
やentries
と呼ばれる別のディレクトリに引き続きエントリを保持できます。このディレクトリはsource_path
の中で定義されます。サブディレクトリ内のエントリポイント用ファイルは、shakacode/shakapacker v6ではサポートされていません。それらのファイルをトップレベルに移動し、それらのファイルの
import
を調整してください。
- 2.
source_entry_path
にネストしたディレクトリが存在しないようにしてください。
エントリポイント用のファイルをsource_entry_path
のサブディレクトリに置いていないかどうかを確認してください。shakacode/shakapacker v6では、サブディレクトリ内のエントリポイントファイルはサポートされていません。これらのファイルをトップレベルに移動し、それらのファイル内のimport
を調整してください。
Shakapacker v6の設定では、JavaScriptのrootディレクトリにエントリポイントを置けるようにするため、ネストは許可されていません。この変更について詳しくはWebpackerの#3156で参照できます。
- 3. WebpackerのgemとNPMパッケージをアップグレードします。
注意: Webpacker gemのページで最新バージョンを確認し、インストールするshakapacker
gemとパッケージのバージョン番号が同一になるようにしてください。
以下は、特定のバージョンにおける例です。
# Gemfile
gem 'webpacker', '6.0.0.rc.6'
bundle install
yarn add @rails/webpacker@6.0.0-rc.6 --exact
bundle exec rails webpacker:install
以下を実行してすべてのファイルを上書きし、変更内容を確認します。
yarn add @babel/core @babel/plugin-transform-runtime @babel/preset-env @babel/runtime babel-loader compression-webpack-plugin terser-webpack-plugin webpack webpack-assets-manifest webpack-cli webpack-merge webpack-sources webpack-dev-server
なお、webpacker:install
はピア依存関係をインストールします。
- 4. 新しいデフォルトの
webpacker.yml
への変更点を確認します。
変更を示唆された箇所を1つずつ慎重に確認してください。特に、source_entry_path
が source_path
のトップレベルになるように変更されていることをチェックしてください。
Webpacker v5では、以下のようにsource_entry_path
にデフォルトでpacks
ディレクトリが使われます。
source_path: app/javascript
source_entry_path: packs
Webpacker v6では、以下のようにデフォルトでトップディレクトリが使われます。
source_path: app/javascript
source_entry_path: /
この設定にしたい場合は、app/javascript/packs/*
(application.js
も含む)をapp/javascript/
に移動し、設定ファイルを更新してください。
なお、このファイル移動は必須ではなくオプションなので、packs
やentries
と呼ばれる別のディレクトリにエントリを引き続き保持することもできます。このディレクトリはsource_path
の中で定義されます。
- 5.
webpack-dev-server
を最新バージョン(4.2より上)にアップデートし、package.json
をアップデートします。 -
6. ビューで使われているAPIを更新します。
具体的には、javascript_packs_with_chunks_tag
ヘルパーをjavascript_pack_tag
ヘルパーに変更し、stylesheet_packs_with_chunks_tag
ヘルパーをstylesheet_pack_tag
ヘルパーに変更します。
注意: 変更の際は、レイアウトやビューで使うjavascript_pack_tag
呼び出しとstylesheet_pack_tag
呼び出しはそれぞれ最大1回までにしてください。これらのビューヘルパーメソッドにはバンドルを複数渡せるようになっています。この変更を忘れてヘルパーメソッドを複数置いてしまうと、パフォーマンスの問題や、Reactの重複読み込みに関連する他のバグが発生する可能性があります(#2932など)。
注意: app/javascript/application.js
ファイル内で、import $ from "expose-loader?exposes=$, jQuery!jquery"
のようにexpose-loader
でjQueryをグローバルに公開している場合は、javascript_pack_tag
にdefer: false
というオプションを渡してください。
- 7.
css
、postcss
、React
、TypeScript
などの統合機能を使っている場合。それらがShakapacker v6でどう機能するかについては、READMEの『integrations』を参照してください。 -
8.
config/webpack/environment.js
のインポート方法はconfig/webpack/base.js
に変更され、ネイティブのwebpackコンフィグをエクスポートするようになったので、toWebpackConfig
を呼び出す必要はありません。
変更には以下のようにmerge
をお使い下さい。
// config/webpack/base.js
const { webpackConfig, merge } = require('@rails/webpacker');
const customConfig = {
module: {
rules: [
{
test: require.resolve('jquery'),
loader: 'expose-loader',
options: {
exposes: ['$', 'jQuery']
}
}
]
}
};
module.exports = merge(webpackConfig, customConfig);
- 9.
.browserslistrc
ファイルにカスタムのブラウザリスト設定がある場合は、その設定をpackage.json
の"browserslist"
キーにコピーして、.browserslistrc
ファイルを削除します。 -
10.
babel.config.js
ファイルをまったくカスタマイズしていない場合は削除します。babelのデフォルト設定を使うには、package.json
で以下のように設定します。
"babel": {
"presets": [
"./node_modules/shakapacker/package/babel/preset.js"
]
}
Reactの設定については、『Customizing Babel Config』ドキュメントのカスタマイズ例を参照してください。
- 11.
webpacker.yml
ファイルからextensions
が削除されました。
カスタム拡張子は、以下のようにオブジェクトをマージする形で自分の設定ファイルに移動してください。詳しくはREADMEの『Webpack Configuration』ドキュメントを参照してください。
{
resolve: {
extensions: ['.ts', '.tsx', '.vue', '.css']
}
}
- 12.
webpacker.yml
ファイルにwatched_paths
がある場合はadditional_paths
に置き換えます。 -
13. #3056で一部の依存関係が削除されました。
Error: Cannot find module 'babel-plugin-macros'
などのエラーが表示された場合は、yarn add <依存パッケージ>
を実行する必要があります(<依存パッケージ>
にはbabel-plugin-macros
、case-sensitive-paths-webpack-plugin
、core-js
、regenerator-runtime
などが含まれます)。これらのパッケージへの依存を取り除くことを検討してもよいでしょう。
- 14.
webpacker.yml
ファイルとconfig/webpack
に適用された設定の新しいデフォルトを確認します。
特に、source_entry_path
を source_path
のトップレベルにするなど、本ガイドで提案されている変更点を注意深く検討してください。
- 15.
bin/webpack
を実行して、エラーが発生しないことを確認します。 -
16.
RAILS_ENV=production bin/rails assets:precompile
を問題なく実行できることを確認します。
確認後、必ずbin/rails assets:clobber
を実行して、生成されたアセットをクリーンアップすること。
- 17.
bin/webpack
やbin/webpack-dev-server
を呼び出すスクリプトを更新して/bin/webpacker
をbin/webpacker-dev-server
に変更します。 -
18.
NODE_ENV
が設定されていない場合、bin/webpacker
およびbin/webpacker-dev-server
のNODE_ENV
はデフォルトでRAILS_ENV
になります。
従来はNODE_ENV
が設定されていない場合はデフォルトでdevelopmentになるため、以前のbinstubでは、config/webpack/development.js
に対応するwebpack設定が使われていました。
変更後は、たとえばRAILS_ENV
が test
の場合はNODE_ENV
もtest
になります。Shakapacker 6.0の最終リリースでは、単一のwebpack.config.js
を使うように変更されました。
- 19. ここまで完了したら、上述のWebpacker v6.0.0.rc.6をShakapacker v6にアップグレードする手順を実行します。
概要
MITライセンスに基づいて翻訳・公開いたします。
表記は「Webpacker」「webpack」「Shakapacker」で統一しました。
以下の記事もどうぞ。