Madogiwa Blog

主に技術系の学習メモに使っていきます。

webpack4系から5系にアップデートした際の対応事項とかメモ

個人で開発しているサービスでフロントエンドのbuildにwebpackを利用しているのですが、4系から5系にアップデートしたので、そのあたりで対応したことをメモしておきます📝

利用していたwebpackのビルド構成

基本的には以下のようなライブラリを利用したBabel + TypeScript + Vueで、 mini-css-extract-plugincssを別ファイルで生成するようにして、webpack-assets-manifestでmanifestを吐き出すような構成です。

  "devDependencies": {
    "@babel/core": "^7",
    "@babel/plugin-transform-runtime": "^7.12.15",
    "@babel/preset-env": "^7.12.1",
    "babel-loader": "^8.1.0",
    "css-loader": "^5.0.0",
    "mini-css-extract-plugin": "^1.3.5",
    "prettier": "2.2.1",
    "rollbar-sourcemap-webpack-plugin": "^3.2.0",
    "sass": "^1.32.6",
    "sass-loader": "^10.1.1",
    "style-loader": "^2.0.0",
    "ts-loader": "^8.0.14",
    "typescript": "^4.1.3",
    "vue-loader": "^15.9.6",
    "vue-template-compiler": "^2.6.12",
    "webpack": "^4.46.0",
    "webpack-assets-manifest": "~4",
    "webpack-cli": "^4.5.0",
    "webpack-merge": "^5.7.3"
  }

webpackアップデート時の対応事項メモ

modeを明示的に指定するようにした

build時に以下の警告が発生するようになり、

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value.
Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

test用のbuildでmodeが指定できていなかったので、以下の通り明示的に指定するようにしました。

process.env.NODE_ENV = "test";

const { merge } = require("webpack-merge");
const common = require("../../webpack.common.js");

module.exports = merge(common, {
  mode: 'production'
});

デフォルトでinstallされなくなったNode.js系のpolyfilをinstallした

webpack5からNode.js関連のpolyfillがinstallされなくなり、以下のようなエラーが発生しました。

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.
If you want to include a polyfill, you need to:
       - add a fallback 'resolve.fallback: { "querystring": require.resolve("querystring-es3") }'
       - install 'querystring-es3'
If you don't want to include a polyfill, you can use an empty module like this:
       resolve.fallback: { "querystring": false }
resolve 'querystring'

私の環境ではquerystring,processといったNode.js由来のmoduleの解決ができなくなっていたので、 以下の通り"querystring-es3",processをinstallして

yarn add querystring-es3 process

もともとのquerystringprocessで参照出来るようにwebpack.config.jsaliasを定義しました。

  resolve: {
    alias: {
      querystring: "querystring-es3",
      process: "process/browser",
    },
  },

そして利用している箇所で適切にimportするようにしてあげて解決しました✨

import process from "process";
import { parse } from "querystring";

[hash]ではなく[contenthash]を利用するようにした

build時に以下の警告が出ていて、

[DEP_webpack_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_HASH] DeprecationWarning: [hash] is now [fullhash] (also consider using [chunkhash] or [contenthash], see documentation for details)

公式のドキュメントを見ると以下の記述があり、

When using [hash] placeholder in webpack configuration, consider changing it to [contenthash]. It is not the same, but proven to be more effective. https://webpack.js.org/migrate/5/#clean-up-configuration

[hash]ではなく[contenthash]が推奨されているようだったので以下の通り、[contenthash]を利用するように修正しました。

  plugins: [
    new MiniCssExtractPlugin({ filename: "[name]-[contenthash].css" }),

[contenthash]はassetの内容に基づいてhashが計算されるようです👀

The [contenthash] substitution will add a unique hash based on the content of an asset. When the asset's content changes, [contenthash] will change as well. https://webpack.js.org/guides/caching/

[fullhash]はbuild時の完全なhashのようなので、[contenthash]の方がassetの内容が変化していなければ、 取得URLが変わらずユーザーのブラウザキャッシュが効くので良いとかそういう話なんですかね?🤔

その他の対応事項

webpack-assets-manifestのデフォルトのファイルパスが変わる

webpack-assets-manifestのバージョンも合わせて5系に上げたのですが、5系からデフォルトのファイル名がmanifest.jsonから、 assets-manifest.jsonに変更になっているようなので、それに合わせてmanifestを参照している箇所をassets-manifest.jsonを参照するにように修正しました。

New in version 5 ⚠️ Updated default value of the output option to be assets-manifest.json. This is to prevent confusion when working with Web app manifests or WebExtension manifests. https://github.com/webdeveric/webpack-assets-manifest/commit/ea293083beda4ddd331246c5f9b76af6d8739f08

そのままmanifest.jsonで読み込みたい場合にはbuild時のオプションでも指定出来るので、そちらを編集するでも良さそうです。

output Type: string Default: assets-manifest.json This is where to save the manifest file relative to your webpack output.path.

おわりに

メジャーバージョンアップということもあり意外と変更点があるなという印象だったのですが、 公式がドキュメントも用意してくれていて非常に助かりました🙏

webpack.js.org