Webpack v4 から v5に上げたので、やったことをまとめる

[Qiita株式会社のカレンダー](https://qiita.com/advent-calendar/2022/qiita-inc)の23日目は @kyntk が担当します。

---

今年、webpackをv4からv5にアップデートしました。
すんなりアップデートとはいかず、いくつか変更したところがあったので、やったことを記載していきます。

元々上げなくてはと思っていたものの着手できていなかったのですが、webpack v4が使っているacornのバージョンに依存して[optional chainingのエラー](https://github.com/webpack/webpack/issues/10227)が起きていたり、watchでCPUをめちゃくちゃ使ってしまうといったことが起きていたりしたので、今回アップデートに踏み切りました。

## v5へのアップデートについて

webpackはv4からv5に上げる際に変更点がとても多いです。それだけでなく、v5でもマイナーバージョンが**75**あるので、影響範囲を確認するだけでも大変でした。

v4からv5で差分が多く、Braking Changeも多いのですが、つまずくポイントはけっこうアプリケーション次第です。設定内容によってはほぼwebpack.config.jsを変えずにアップデートできることもあります。
(実際、今回とは別のアプリケーションではすんなり上げることができました)

## 参考ドキュメント

v4からv5へのmigrate手順はここに書かれています。

https://webpack.js.org/migrate/5/

リリースされた内容はこちらですが、大量にあります。 (後半はInternal Changesで、アプリケーション開発者にはあまり関係はないです)

https://webpack.js.org/blog/2020-10-10-webpack-5-release/

## Migrate手順

[Migrateガイド](https://webpack.js.org/migrate/5/)に則ってやっていきます。

0\. Node.js 10.13.0 (LTS)以上に上げる
1\. webpack 4の最新バージョンに上げる
2\. webpack-cliを最新バージョンに上げる
3\. 使用しているPluginsとLoadersを最新の利用可能バージョンに上げる
4\. warningやerrorが出ないかを確認。いくつかの設定項目を変更する
5\. webpackを最新バージョンに上げる
6\. 使えなくなった、使わなくなった設定の変更をする

のような流れで進めます。
ここからいくつかピックアップして説明していきます。

### 3\. 使用しているPluginsとLoadersを最新の利用可能バージョンに上げる

使っているLoader、Pluginの数が多かったのと、使っていたもののversionが古かったため差分が多かったので、地味に面倒でした。

またcss-loaderがpostcssのバージョンに依存したり、あるバージョンからwebpack v5が必須になるものもあることで「Loaderアップデート → webpack v5へアップデート → Loaderアップデート」のように進める必要もありました。

#### css-loaderのBraking Changeに躓いた

css-loader v4から絶対パスでのurlの解決ができなくなりました。

https://github.com/webpack-contrib/css-loader/issues/1136#issuecomment-664984703

そのため、publicディレクトリに、画像やフォントなどをおいておき、以下のように参照していたところがあったのですが、この修正が必要でした。

```css
.hoge {
  background-image: url("/assets/hoge.png");
}
```

### 5\. webpackを最新バージョンに上げる

先程も掲載しましたが、とにかく差分、Braking Changeが多いです。 (以下のドキュメントの`MIGRATION`というところを見ると良いです)

https://webpack.js.org/blog/2020-10-10-webpack-5-release/

そもそもwebpackについての知識もあまりなかったので、基本のところから勉強して、自分でいじったりしながら学びました。

#### [Automatic Node.js Polyfills Removed](https://webpack.js.org/blog/2020-10-10-webpack-5-release/#automatic-nodejs-polyfills-removed)

webpack v4まではNode.js API互換のライブラリが[fallback](https://webpack.js.org/configuration/resolve/#resolvefallback)として自動で追加されていたのですが、それがなくなりました。
そのため、必要なライブラリを個別で設定する必要があります。

今回主にハマったのはここです。

アップデートをしたのが、V8上でSSRをしているアプリケーションでした。V8にはNode.jsのAPIは備わっていないため、クライアント側だけでなく、サーバーサイド側でもNode.js APIの機能をもつライブラリをインストールする必要がありました。

更に、アプリケーションで[isomorphic-fetch](https://www.npmjs.com/package/isomorphic-fetch)を使っていたのですが、このライブラリが、いくつかのNode.js APIがGlobalに定義されている前提で呼び出されており、これらの整合性をとろうと思うと、クライアント側にも不要なライブラリが展開されてしまったりしました。
その結果、バンドルサイズが拡大して、ビルド時間も伸びるという問題に直面し、これの対策をする必要がありました。

#### その他の細々修正

- [EnvironmentPlugin](https://webpack.js.org/plugins/environment-plugin/)で初期値がundefinedのものがエラーになったので変更した
- [@types/webpack は要らなくなった](https://github.com/webpack/changelog-v5/blob/master/README.md#typescript-typings)ので削除した
- [hash] → [contenthash] へ変更
- など

結果、webpack.config.jsの細かい設定はほぼ書き換えずに済みました。
その他、webpack-bundle-analyzerのアップデートや、url-loaderやcache-loaderなど、deprecatedになっていたものの対応もありましたが、まずはアップデートをし、後から更新をしました。

## まとめ

JavaScriptのビルドやバンドラーの設定周りを今までガッツリ触ったことがなかったのですが、このアップデートを通して理解を深めることができたので、ビルドの設定をある程度自由に書き換えることができるようになりました。
また、JavaScriptランタイムごとの違い、ブラウザごとの違いなどもそこまで意識してこなかったのですが、「V8では使えないNode.jsのAPI」「ブラウザでもNode.jsでも使えるAPI」などを知る機会になりました。

ライブラリのアップデートは計画的に。

---

[Qiita株式会社のカレンダー](https://qiita.com/advent-calendar/2022/qiita-inc)24日目は @degudegu2510 と @inukai-masanori が担当します！

もう少しでクリスマスになりますが、[Qiita株式会社のカレンダー](https://qiita.com/advent-calendar/2022/qiita-inc)を購読設定して、明日の記事もご覧いただけると嬉しいです。