webpack 5にアップデート


webpackを ^4.44.0 -> ^5.0.4にマイグレーションしましたので、
その際の作業の覚書です。



## migrationの仕方
https://webpack.js.org/migrate/5/
基本的に上記の公式を読みつつ、エラーが出たらその都度エラー文を元に対応していく形で進めました。
元々のwebpackの設定にもよって対応も変わってくるかと思いますが、
主要な変更箇所と実際に私が変更した箇所を紹介しておきます。

## loaderとuseの厳格化
【参考】　https://blog.hiroppy.me/entry/webpack5
`rules.loader`と`rules.use`の使用ルールが厳格になったことで、
環境によってはエラーとなる可能性があります。
optionsを使用しない場合は `use`、
optionsを使用する場合は`loader`となるように設定を見直しましょう。


## optionsのアップデート
今回のアップグレードでいくつかのoptionsはoutdatedとなり、他のものに変える必要があります。

(以下、公式から)

>- optimization.hashedModuleIds: true ↦ optimization.moduleIds: 'hashed'
- optimization.namedChunks: true ↦ optimization.chunkIds: 'named'- ・optimization.namedModules: true ↦ optimization.moduleIds: 'named'
- NamedModulesPlugin ↦ optimization.moduleIds: 'named'
- NamedChunksPlugin ↦ optimization.chunkIds: 'named'
- HashedModulesPlugin ↦ optimization.moduleIds: 'hashed'
- optimization.noEmitOnErrors: false ↦ optimization.emitOnErrors: true
- optimization.occurrenceOrder: true ↦ optimization: { chunkIds: 'total-size', moduleIds: 'size' }
- optimization.splitChunks.cacheGroups.vendors ↦ optimization.splitChunks.cacheGroups.defaultVendors
- Compilation.entries ↦ Compilation.entryDependencies
- serve ↦ serve is removed in favor of DevServer

私の場合は `NamedModulesPlugin`を使用していたため、その設定を見直しました。
これは`HMR(ホットモジュールリロード)` のためのoptionsですが、指示通り`optimization`の設定に変更しました。

```diff:webpack.config.js
  plugins: [
-   new webpack.NamedModulesPlugin(),
    ...
  ],
  optimization: {
+    moduleIds: 'named',
+    ...
  }
```

しかし、その後の公式の文にこんなものが。
>Consider removing optimization.moduleIds and optimization.chunkIds from your webpack configuration. The defaults could be better, because they support long term caching in production mode and debugging in development mode.

(雑訳)`optimize.moduleIds`と`optimization.chunkIds`の設定を削除することを検討してください。
デフォルトだとproductionモードでは長めのキャッシュを、developmentモードではデバックをサポートしますよ。

😕

ということで、色々検討した結果`moduleIds`も外すことにしています...

```webpack.config.js
  optimization: {
-    moduleIds: 'named',
     ...
  }
```


## その他細かい設定
>When using [hash] placeholder in webpack configuration, consider changing it to [contenthash]. It is not the same, but proven to be more effective.
If you are using Yarn's PnP and the pnp-webpack-plugin, we have good news: it is supported by default now. You have to remove it from the configuration.
If you are using IgnorePlugin with a regular expression as argument, it takes an options object now: new IgnorePlugin({ resourceRegExp: /regExp/ }).
If you are using node.something: 'empty' replace it with resolve.fallback.something: false.

### file-loader
色々ありますが、 私は [hash]を`file-loader`で使用していたので
[contenthash]に変える作業が発生しました。
また、`file-loader`はクエリでのoption指定から`options`での指定にかわったようなので、こちらも調整します。

```diff:webpack.config.js
  module: {
    rules: [
      {
         ...
         test: /\.(jpe?g|png|gif|svg)$/i,
-        loader: 'file-loader?name=css/img/[name].[ext]?[hash]',
+        loader: 'file-loader',
+        options: {
+           name: 'css/img/[name].[ext]?[contenthash]',
+        },
      ...
```

### IgnorePlugin
IgnorePluginの指定方法も変わっていますので、
設定されている場合はそちらの記述も変更します。
私はmoment.jsのために使用していたので記述を変更しました。（そもそもmoment.jsやめないとなあ...)

```diff:webpack.config.js
-    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
+    new webpack.IgnorePlugin(
+      {
+        resourceRegExp: /^\.\/locale$/,
+        contextRegExp: /moment$/,
+      },
+    ),
```


### 古いパッケージやエコシステムの見直しを
私の環境では`optimize-css-assets-webpack-plugin`が原因でエラーとなっている部分がありました。
"optimize-css-assets-webpack-plugin": "^3.2.1",　だったので、
"optimize-css-assets-webpack-plugin": "^5.0.4"　に変更したところエラーが解消されました。
この辺も一通り見直さないといけないですね。


## 俺たちの戦いはこれからだ!
上記作業で一通り動作の問題なさそうなものの、 `deprecationWarning`がめっちゃ出てます。
こちらも見直さなければ....
余裕があればその解消の作業も追記していきます。

最後に、公式手順にlevel別stepがのっていましたのでざっくり意訳しておきます。
公式ではLevel7までありますが、最低でも3 or4レベルまで繰り返してとのことです。

```
Level1.  スキーマバリデーションエラー。BREAKING CHANGE: 
といったエラーや、代替オプションにしたがってoptionを変更すること！

Level2.  webpackエラー。エラーメッセージをよめ！エラーメッセージが全て教えてくれる。

Level3.  ビルドエラー。BREAKING CHANGE: といったエラーが出ているはず。 読め。

Level4.  ビルドワーニング。　ワーニングメッセージは改善点を示してくれます。
```