Webpack5 alpha の近況をのぞいてみた

こんばんわ！クリスマスもあと残りわずか、ギリギリのポストです！
[LOB Advent Calendar](https://qiita.com/advent-calendar/2018/lob-inc) もこれが最終日でございます。
昨日は @cheung-chifung による [まだClean Architectureで消耗しているの?](https://qiita.com/cheung-chifung/items/0355a77b01379aaf945a) でした。

ここまで今年のアドベントカレンダーに協力してくれたエンジニアチームに全力で感謝をしつつ、 2018 年ラストの記事をお届けします。


# そろそろ Webpack 5 でるっぽいよ
ぶっちゃけ（歴史的経緯とか）そんなに詳しいわけじゃないんですけど今回はフロントエンドでバリバリやってるエビバディがお世話になっているであろう Webpack ネタでございます。

それなりのものを犠牲にした結果、爆速なビルドを実現した Parcel の登場もつかの間、 60-90 % 級のパフォーマンス改善( Parcel 関係なく予定されてたらごめんなさい)を実現した v4 。
そろそろ v5 の産声があがりそうな雰囲気でいっぱいになってきました。
MileStone 的には No due date ですが、あと一息、というような状態でしょうか。

<img width="1042" alt="スクリーンショット 2018-12-25 22.21.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/28612/a6397e02-5ea5-2b27-0c0b-989b4f037bac.png">


まずは Changelog から何が起きそうなのか拾ってみましょう。

# [Changelog](https://github.com/webpack/changelog-v5/blob/master/README.md)

以下 General Direction の意訳でございます。(誤訳だったらごめんなさい、編集リクエストください)

- 永続化させたキャッシュを使用することでビルドパフォーマンスを向上を試みています
- より良いアルゴリズムとデフォルト化で長期キャッシングの改善を試みています
- v4 で features を実装している間、breaking changes を行えず珍妙な状態のままだった内部構造の整理を試みています
- future features のために breaking changes を現段階で入れておくことで、できるだけ長く v5 を使い続けられるようなものにできるよう試みています


リファクタしつつ、さらなるパフォーマンスチューニングを施している、といったところでしょうか。
主な差分は以下とのことです。

- Removed Deprecated Items
- Automatic Node.js Polyfills Removed
- Deterministic Chunk and Module IDs
- Named Chunk IDs
- Compiler Idle and Close
- SplitChunks and Module Sizes
- Persistent Caching
- Minimum Node.js Version

意訳はあきらめました。
長くメンテされ続けているプロジェクトにとって特に大きなものは Node.js の Minimum version が 6 系から 8 系に引き上げられたところでしょうか。
また、 v4 で deprecated となっていたものが v5 で削除されているようです。 v4 時点で deprecated な warning をスルーしているなら今のうちに潰しておいたほうがよさそうですね！
とはいえ Polyfill が削除されたことによる各パッケージや実装への影響が大きそうな予感もなかなかのものです events とか。

これまでメモリ上にのせて管理していたキャッシュですが、 永続化可能な cache.type: filesystem が新規追加されています。
この変更に伴い webpack.config.js の cache 周りの設定に大きな変更が入っていますが、cache に限らず `Removed Deprecated Items` や `Automatic Node.js Polyfills Removed` によるものも多そうです。
物量が多いのでこれはそのまま貼っておきますね。

```
## Changes to the Structure

- `cache: Object` removed: Setting to a memory-cache object is no longer possible
- `cache.type` added: It's now possible to choose between `"memory"` and `"filesystem"`
- New configuration options for `cache.type = "filesystem"` added:
  - `cache.cacheDirectory`
  - `cache.name`
  - `cache.version`
  - `cache.store`
  - `cache.loglevel`
  - `cache.hashAlgorithm`
- `resolve.cache` added: Allows to disable/enable the safe resolve cache
- `resolve.concord` removed
- Automatic polyfills for native node.js modules were removed
  - `node.Buffer` removed
  - `node.console` removed
  - `node.process` removed
  - `node.*` (node.js native module) removed
  - MIGRATION: `resolve.alias` and `ProvidePlugin`. Errors will give hints.
- `optimization.chunkIds: "deterministic"` added
- `optimization.moduleIds: "deterministic"` added
- `optimization.moduleIds: "hashed"` deprecated
- `optimization.moduleIds: "total-size"` removed
- Deprecated flags for module and chunk ids were removed
  - `optimization.hashedModuleIds` removed
  - `optimization.namedChunks` removed (`NamedChunksPlugin` too)
  - `optimization.namedModules` removed (`NamedModulesPlugin` too)
  - `optimization.occurrenceOrder` removed
  - MIGRATION: Use `chunkIds` and `moduleIds`
- `optimization.splitChunks` sizes can now be objects with a size per source type
  - `minSize`
  - `maxSize`
  - `maxAsyncSize`
  - `maxInitialSize`
- `optimization.splitChunks` `maxAsyncSize` and `maxInitialSize` added next to `maxSize`: allows to specify different max sizes for initial and async chunks
- `optimization.splitChunks` `name: true` removed: Automatic names are no longer supported
  - MIGRATION: Use the default. `chunkIds: "named"` will give your files useful names for debugging
- `optimization.splitChunks.cacheGroups[].idHint` added: Gives a hint how the named chunk id should be chosen
- `optimization.splitChunks` `automaticNamePrefix` removed
  - MIGRATION: Use `idHint` instead
- `output.devtoolLineToLine` removed
  - MIGRATION: No replacement
- `output.hotUpdateChunkFilename: Function` is now forbidden: It never worked anyway.
- `output.hotUpdateMainFilename: Function` is now forbidden: It never worked anyway.
- `stats.chunkRootModules` added: Show root modules for chunks
- `stats.orphanModules` added: Show modules which are not emitted
- `stats.runtime` added: Show runtime modules
- `stats.chunkRelations` added: Show parent/children/sibling chunks (since alpha.1)
- `stats.preset` added: select a preset (since alpha.1)
- `BannerPlugin.banner` signature changed
  - `data.basename` removed
  - `data.query` removed
  - MIGRATION: extract from `filename`
- `SourceMapDevToolPlugin` `lineToLine` removed
  - MIGRATION: No replacement
- `[hash]` as hash for the full compilation is now deprecated
  - MIGRATION: Use `[fullhash]` instead or better use another hash option
- `[modulehash]` is deprecated
  - MIGRATION: Use `[hash]` instead
- `[moduleid]` is deprecated
  - MIGRATION: Use `[id]` instead
- `[filebase]` removed
  - MIGRATION: Use `[base]` instead
- New placeholders for file-based templates (i. e. SourceMapDevToolPlugin)
  - `[name]`
  - `[base]`
  - `[path]`
  - `[ext]`
- `externals` when passing a function, it has now a different signature `({ context, request }, callback)`
  - MIGRATION: Change signature
```


その他にも、マイナー系の変更が非常に多く含まれているようです。

# 実際どんなもんなのよパフォーマンス
さっとアプリを書いて計測しようと思ってましたが、 Webpack v5 のビルドパフォーマンスについて言及したツイートを発見しましたのでこちらをご紹介。
<blockquote class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">Just tried our Persistent file caching. Just on tiny and preliminary results the build time reductions seem incredible. <br><br>🚨🔥 Pre: webpack 5-next / mode: production / cache: filesystem - 4292ms<br>🚨🔥 Post: webpack 5-next / mode: production (run 2) / cache: filesystem -  979ms<br><br>🙀 <a href="https://t.co/f40ESGlD0A">pic.twitter.com/f40ESGlD0A</a></p>&mdash; Sean Thomas Larkin (肖恩) (@TheLarkInn) <a href="https://twitter.com/TheLarkInn/status/1069246795031576576?ref_src=twsrc%5Etfw">2018年12月2日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

4292 ms だった初回ビルドが 2 回目実行時には 979 ms に短縮したとのことですね。
もともと時間かかりすぎやろっていうお気持ちはさておき、 4 倍に高速化するのはなかなかの成果っぷりなのではないでしょうか。

# まとめ

さくさく機敏に動いてくれないマシンをなぐりとばしそうになってしまうせっかちな僕は、 v5 のおかげで安らかな気持ちで React 爆速ホットリロードライフを送れそうな予感がしています。
弊社では TypeScript とあわせて React を利用しているため、 tsc -> babel -> es5 という経路をたどっているのですが、[不穏なフィードバックを眺めつつ](https://github.com/webpack/webpack/issues/8537#issuecomment-449667787) public な v5 でこのビルドフローが一体どこまで高速になるのか今から楽しみです。

現状でもキャッシュを利用してそれなりに高速化をしているものの、まだまだ遅く MacBook Pro の発熱がえげつないので困っているのですが、
無印 MacBook でもストレスなく開発できるようになったらいいな、とまだ見ぬサンタとトナカイへ祈りを捧げながら今宵は眠りにつこうと思います。

では、メリークリスマス！

# 余談
[株式会社LOB](https://lob-inc.com) では、楽天経済圏のアセットを活用した広告プラットフォームを一緒に開発してくれるメンバーを積極的に採用しております。
TypeScript & React によるフロントエンド開発や Go / Java によるサーバーサイド開発に興味がある方はぜひご応募ください！