webpackを4から5へアップデートしました。エラーはちょいちょい出ていて、うまく行ってるところ、そうじゃないところがあります。
ひとつひとつ見ていきましょう。
これは移行作業の序の口です。その後にプラグインのアップデート、エラーが出たらその修正が必要です。
変更前 | 変更後 | |
---|---|---|
webpack | 4.44.2 | 5.3.2 5.4.0 5.8.0 |
webpack-cli | 3.3.12 | 4.1.0 4.2.0 |
プラグイン | バージョン変更前 |
---|---|
babel-loader | 8.1.0 8.2.2 |
@babel/core (babel-loaderで必要。) | 7.12.3 7.12.9 |
@babel/preset-env (babel-loaderで必要。) | 7.12.1 7.12.7 |
@babel/plugin-transform-react-jsx (Reactのjsxで必要。) | 7.12.5 7.12.7 |
html-loader | 1.3.2 |
style-loader | 2.0.0 |
css-loader | 5.0.1 |
postcss-loader | 4.0.4 4.1.0 |
postcss (postcss-loaderで必要。) | 7.0.32 |
autoprefixer (postcssのプラグイン) | 9.8.6 |
sass-loader | 10.0.5 10.1.0 |
node-sass (sass-loaderで必要。) | 5.0.0 |
mini-css-extract-plugin | 1.3.0 1.3.1 |
copy-webpack-plugin | 6.3.0 6.3.2 |
html-webpack-plugin | 4.5.0 |
html-webpack-skip-assets-plugin | 0.0.2 |
core-js | 3.7.0 3.8.0 |
2020年10月10日、webpackのメジャーバージョンが4から5へ上がりました。2年半弱ぶりくらいでしょうか?
ドキュメントを見ると『機能が完全であることさえ意味しません。』と言っているので、時期尚早の感はあります。
(執筆時点2020年10月30日ですでに、マイナーバージョンが3まで進んでいるところからも分かる。)
が、環境によってはスムーズに行くかもしれないし、やりようによっては簡単な修正で済むかもしれません。
ここは『百聞は一見にしかず』で行ってみようと思います。
アップデート後なにもせずに実行
(前提として、webpack4の環境でパッケージのバージョンを正常に動く最新バージョンにアップデートしておきます。)
まずはじめに、webpack, webpack-cliをアップデートしただけで実行しました。気になるところが出ています。
エラー2件。警告1件
結果のHTMLが縮小されない。(整形されたフォーマットのまま。)
実行時間が長くなる。(+5~10秒)
エラーは2件。
PS C:\webpack5-pj> yarn build
yarn run v1.22.10
$ webpack --mode=production --display-error-details & yarn external-css & yarn cleanup
[webpack-cli] Unknown argument: --display-error-details
? Which flags do you want to use? ...
√ --entry: The entry point(s) of your application e.g. ./src/main.js
√ --config: Provide path to a webpack configuration file e.g. ./webpack.config.js
√ --color: Enable/Disable colors on console
√ --merge: Merge two or more configurations using webpack-merge e.g. -c ./webpack.config.js -c ./webpack.test.config.js --merge
√ --progress: Print compilation progress during build
√ --help: Outputs list of supported flags
√ --output-path: Output location of the file generated by webpack e.g. ./dist/
√ --target: Sets the build target e.g. node
√ --watch: Watch for files changes
√ --hot: Enables Hot Module Replacement
√ --devtool: Determine source maps to use
√ --prefetch: Prefetch this request
√ --json: Prints result as JSON or store it in a file
√ --mode: Defines the mode to pass to webpack
√ Which flags do you want to use? · No items were selected
[webpack-cli]
Executing CLI
(node:32) [DEP_WEBPACK_COMPILATION_ASSETS] DeprecationWarning: Compilation.assets will be frozen in future, all modifications are deprecated.
BREAKING CHANGE: No more changes should happen to Compilation.assets after sealing the Compilation.
Do changes to assets earlier, e. g. in Compilation.hooks.processAssets.
Make sure to select an appropriate stage from Compilation.PROCESS_ASSETS_STAGE_*.
[webpack-cli] Error: Prevent writing to file that only differs in casing or query string from already written file.
This will lead to a race-condition and corrupted files on case-insensitive file systems.
C:\webpack5-pj\dist\sample\smooth-scroll\index.html
C:\webpack5-pj\dist\sample\smooth-scroll\index.html
at writeOut (C:\webpack5-pj\node_modules\webpack\lib\Compiler.js:565:20)
at C:\webpack5-pj\node_modules\webpack\lib\util\fs.js:178:5
at FSReqCallback.oncomplete (fs.js:156:23)
PS C:\webpack5-pj>
うまく行っているところとして、
CSS(SASS)はwebpack4と同じ結果。
JavaScriptの結果に問題なし。(むしろサイズが小さくなってありがたい。)
webpack5になって一番いいところは、『変更のあるファイルだけ更新される』こと。
これまでは、CSSだけ変更しているのにJavaSciprtやHTMLもビルドされて結果ファイルのタイムスタンプが変わってました。
ソース管理している側としては、変更したものだけをビルドしてくれるのでありがたいです。
ダメなところはエラーを直してみないと何とも言えないので、エラーを直すところから始めます。
--display-error-detailsオプション削除
まずは1個めのエラーから。
PS C:\webpack5-pj> yarn build
yarn run v1.22.10
$ webpack --mode=production --display-error-details & yarn external-css & yarn cleanup
[webpack-cli] Unknown argument: --display-error-details
? Which flags do you want to use? ...
√ --entry: The entry point(s) of your application e.g. ./src/main.js
√ --config: Provide path to a webpack configuration file e.g. ./webpack.config.js
√ --color: Enable/Disable colors on console
√ --merge: Merge two or more configurations using webpack-merge e.g. -c ./webpack.config.js -c ./webpack.test.config.js --merge
√ --progress: Print compilation progress during build
√ --help: Outputs list of supported flags
√ --output-path: Output location of the file generated by webpack e.g. ./dist/
√ --target: Sets the build target e.g. node
√ --watch: Watch for files changes
√ --hot: Enables Hot Module Replacement
√ --devtool: Determine source maps to use
√ --prefetch: Prefetch this request
√ --json: Prints result as JSON or store it in a file
√ --mode: Defines the mode to pass to webpack
√ Which flags do you want to use? · No items were selected
専用コマンドwebpack-cliのエラーです。webpack-cliのメジャーバージョンも3から4に上げたのが影響しました。
(webpack5を使うにはcliのバージョン4が必要。)
何やらたくさんのメッセージが出ているのは、使えるオプションのリストが出ているから。
--display-error-detailsオプションが無くなりました。無いものはしょうがないので削除します。
代わりのオプションはありません。
webpack-bundle-analyzerをインストールして、--analyzeオプションを使うのが一番近そう。
pluginsの結果ファイルが重複したらダメ
もう一つのエラーです。
[webpack-cli] Error: Prevent writing to file that only differs in casing or query string from already written file.
This will lead to a race-condition and corrupted files on case-insensitive file systems.
C:\webpack5-pj\dist\sample\smooth-scroll\index.html
C:\webpack5-pj\dist\sample\smooth-scroll\index.html
at writeOut (C:\webpack5-pj\node_modules\webpack\lib\Compiler.js:565:20)
at C:\webpack5-pj\node_modules\webpack\lib\util\fs.js:178:5
at FSReqCallback.oncomplete (fs.js:156:23)
PS C:\webpack5-pj>
エラー: 既に書き込まれたファイルと大文字小文字やクエリー文字列(URLパラメータ)が異なるだけのファイルへの書き込みを防止します。
大文字小文字が区別されないファイルシステムでは競合状態が発生し、ファイルが破損します。
筆者訳
説明の前に、webpack.config.jsの内容です。
const mode = require("./webpack.config/mode");
const getEntry = require("./webpack.config/entry");
const entry = getEntry();
const rules = require("./webpack.config/module/rules");
const dir = require("../../../directory-path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyPlugin = require("copy-webpack-plugin");
const HtmlWebpackSkipAssetsPlugin = require("html-webpack-skip-assets-plugin")
.HtmlWebpackSkipAssetsPlugin;
const dir = require("./directory-path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
/**
* htmlにjs, cssを差し込んでビルド
*/
const htmlWebpackPluginSample = (html, minify, excludeAssets) => {
return new HtmlWebpackPlugin({
filename: dir.sample + html,
template: dir.src.sample + html,
minify: minify,
// css, jsのhtml差し込み除外
excludeAssets: excludeAssets,
});
};
module.exports = {
mode: mode.MODE,
entry: entry,
module: {
rules: rules,
},
plugins: [
new MiniCssExtractPlugin({ filename: "[name].css", }),
/**
* srcからコピーするだけ
*/
new CopyPlugin({
/**
* 対象
*
* /sample/配下のhtml
*
* 除外
*
* /rwd-base/index.html
*/
patterns: [
{
from: "**/*.html",
to: dir.sample,
context: dir.src.sample,
globOptions: {
dot: false, // .***のファイルは除外
gitignore: false, // falseじゃないとエラーになる。
ignore: [
"**/rwd-base/index.html",
],
},
},
],
}),
/**
* HTML別出し。
*
* 自動的にプロジェクトのjs, cssをhtmlに突っ込む。
*/
htmlWebpackPluginSample(
"/rwd-base/index.html",
true,
excludeAssetsForSample.concat([
/\/sample\/smooth-scroll\/*/,
])
),
htmlWebpackPluginSample(
"/smooth-scroll/index.html",
true,
excludeAssetsForSample.concat([
/\/sample\/rwd-base\/*/,
])
),
new HtmlWebpackSkipAssetsPlugin(),
];
};
(今回はplugins以外は関係ないので、そのあたりの説明は割愛。)
この設定では2パターンのHTML出力を行っています。
プラグイン | 何をする? | HTMLファイル |
---|---|---|
copy-webpack-plugin | srcのHTMLをコピーして出力。 (webpackで何もしない。) | すべてのHTML |
html-webpack-plugin | HTMLにJSとCSSを入れて、サイズを圧縮して出力 | /rwd-base/index.html /smooth-scroll/index.html |
基本的にHTMLはコピー出力で、2ファイルだけwebpackのバインドを使って出力するもの。
エラーの内容は、
/smooth-scroll/index.htmlはコピー出力したのに、別の方法でまた出力してるよ?
と言っています。
webpack4では、webpack.config.jsの設定順で上書きしてくれていました。webpack5ではエラーになるらしい。
ということで、copy-webpack-pluginの除外設定を修正します。
// (省略)
module.exports = {
// (省略)
plugins: [
/**
* srcからコピーするだけ
*/
new CopyPlugin({
/**
* 対象
*
* /sample/配下のhtml
*
* 除外
*
* /rwd-base/index.html
* /smooth-scroll/index.html <--- 追加
*/
patterns: [
{
from: "**/*.html",
to: dir.sample,
context: dir.src.sample,
globOptions: {
dot: false, // .***のファイルは除外
gitignore: false, // falseじゃないとエラーになる。
ignore: [
"**/rwd-base/index.html",
"**/smooth-scroll/index.html", // <--- 追加
],
},
},
],
}),
// (省略)
];
};
webpack4では上書きしてたことで気づきませんでしたが、そもそも、出力ファイルの重複はボクの設定ミスです。
ちょっと気になったのは大文字小文字の区別をしないところですね? ボクはそんなややこしいHTMLファイル名をつけないのでどうでもいいですが。
(HTMLファイル名はスペルをユニークにするのが普通。)
今回、pluginsでのHTML出力で起きましたが、rulesでのjs, cssでも起きるかも知れません。
ファイル名の重複はフルパスで判定します。
たとえば、パスが違えばindex.htmlやmain.jsを複数作ってもOK。
警告はとりあえず放置
あと残るは警告の修正です。
[webpack-cli]
Executing CLI
(node:32) [DEP_WEBPACK_COMPILATION_ASSETS] DeprecationWarning: Compilation.assets will be frozen in future, all modifications are deprecated.
BREAKING CHANGE: No more changes should happen to Compilation.assets after sealing the Compilation.
Do changes to assets earlier, e. g. in Compilation.hooks.processAssets.
Make sure to select an appropriate stage from Compilation.PROCESS_ASSETS_STAGE_*.
警告: Compilation.assetsは将来的に凍結され、すべての変更は非推奨となります。
BREAKING CHANGE: Compilationを封印した後、これ以上の変更はCompilation.assetsに起こるべきではありません。
例えば、Compilation.hooks.processAssetsのように、より早い段階でアセットに変更を加えてください。
Compilation.PROCESS_ASSETS_STAGE_*から適切なステージを選択してください。
筆者訳
結果から言うと放置。アセットを変更するプラグインが影響していると予想します。
webpackのデフォルトでは、css, jsをすべて詰め込んだjsファイルをひとつだけindex.htmlに組み込むバインドを行います。
(SPAの造り)
CSSの別出しやjsに詰め込まずHTMLにjs, cssを組み込むなど、バインドを変えるようなプラグインが影響していると思われる。
エラーにならないかぎり、プラグイン・パッケージのアップデートで修正されることを期待します。
JavaScriptのサイズが小さくなる
今回webpackをバージョン5にアップデートして見るからに変わったのはJavaScriptのサイズが小さくなったこと。
minimize(縮小化)には難読化も含まれていることも多いですが、そのレベルが上ったようです。
(難読化は変数名やオブジェクト名などをa,b,cなど意味のないものに変換すること。)
また、reactを使ったときにコメントが追加されますが、そのコメントをテキストファイルに別出しするようになっています。
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/
/** @license React v17.0.1
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
テキストファイルは、jsファイルの出力先と同じところに [jsファイル名].LICENTSE.txtで出力されます。
サイトのパフォーマンス向上にとってありがたい。
バージョンアップ作業はここから本番
今回の作業でとりあえずビルドは正常に行われますが、お見せした部分はwebpack4 -> webpack5への移行作業の準備に過ぎません。
移行作業のメインは、webpack.config.jsの内容をバージョン5用に修正することです。
だから警告をとりあえず放置したし、webpackの実行時間が長いのも無視しました。
(設定の修正が終わっても直らないようなら、そのときに考えればいい。)
移行のガイダンスはwebpack.js.orgに公開されています。
移行ガイドを読みましたが、結果、webpack.config.jsの修正はありませんでした。
ローダーやプラグインをインストールして使う程度なら修正することはあまりありません。
もっと凝ったカスタムをした人向けの印象。
出ていた警告(DeprecationWarning)の放置もそのまま。移行ガイドでも、プラグインはコア機能に追いつくのに時間がかかると言っているし、比較的大したことないとも言ってるので。
実行時間がかかるのも、とりあえず放置。webpack5では、モードがproductionのときはデフォルトでキャッシュを使うらしい。
これ以上のパフォーマンス向上はカスタムの領域。
ということでボクの移行作業はここで終了にしました。