ViteでJavaScriptプロジェクトをビルドしてみたところ、想定以上に細切れとなりましたが、調整したら緩和できました。
TL; DR
- ViteはES Moduleネイティブで、ブラウザの
import
を使うような結果を生成する - コードの過不足がないように分割するので、細かくなりすぎることがある
- Rollup側の
output.experimentalMinChunkSize
で改善可能
ViteとWebpackの違い
既存のプロジェクトをWebpackからViteに乗り換えたのですが、考え方が大きく異なりました。
Webpackは、CommonJS全盛期の2014年に初版が作られたソフトウェアで、のちにES Moduleにも対応してきたとはいえ、モジュール管理はWebpack自身が追加したコードによって処理されています。また、CommonJS
ではモジュールの呼び出しがrequire
という関数であるため、モジュールの切れ目はコードを書く側が意識しなければならず、うっかりすると同じモジュールが複数箇所に取り込まれる、ということになってしまいました。
これに対してViteは、ES Moduleのブラウザネイティブ対応が進んでから登場したツールで、Vite自身が取り扱うモジュール構造も出力結果もES Moduleとなっており、import
/export
もブラウザにある機能をそのまま使う形となっています1。
そして、import
が静的な構文ということもあり、もとのソースコードでimport
されていたファイルを別ファイルとしておく、ということも当たり前に行われて、同じコードが重複しないことを優先する形のビルド結果となります。
気になった問題点
そこまではいいのですが、動的なimport()
でファイルを切り分けるようにしていたプロジェクトで、「このファイルはこっちに入る」というパターンが細分化されてしまい、最小は文字列定数が1つというようなファイルを含め、100個以上のJavaScriptファイルが散らかる事態となってしまいました。
流石にここまで来ると、過不足なくコードを読み込めるメリットより、ファイル数が増えるデメリットを考えざるを得ません。
設定による対策
調べてみると、Viteから使うRollup側の設定にoutput.experimentalMinChunkSize
というものがありました。
ドキュメントで詳細を確認してみましたところ、概ね以下のような感じでした。
- 指定した容量以上になることを目指してチャンクをまとめる
- まとめた結果として、使わないコードが付いてくる形になる箇所が発生する
- 容量の基準はTree shaking後、minify前
- 副作用などを考え合わせて、マージされないこともありうる
実際に指定をかけた結果、JavaScriptチャンクは半減以下となりました。なお、動作を見ていたところ、「ふつうにチャンクを作る」→「マージできるか調べる」という流れになっていました。そして副作用があるとの判断で別チャンクになった箇所も確認できました。
-
Viteの開発モードではバンドルも積極的には行わず、ソースコードの1ファイル単位で変換を行ってはブラウザで直接読み込むという構造となりますが、今回の主題はリリースビルドの方なので、そちらを掘り下げるのは割愛します。 ↩