Viteで意外と知られていないSplitVendorChunkPluginでチャンク戦略を図る
こんにちは。とあるフロントエンドエンジニアです。
最近はフロントエンド系のフレームワークなどのバンドラー部分ではViteが必ずと言っていいほど入っていますね。
Viteはビルドの設定をvite.config.jsで簡単に記述できるのも魅力ですね✨
そんなViteの意外と知られていない?プラグインの1つにSplitVendorChunkPluginがあります。
そこで今回は、SplitVendorChunkPluginの概要や導入するメリット、具体的なユースケースについて紹介していこうと思います。ですがSplitVendorChunkPluginの説明に入る前に、前提となるチャンク戦略について軽くおさらいします。
そもそもチャンク戦略とは
JSのバンドルのおさらい
JSのバンドルは、Webアプリケーションのパフォーマンスを向上させるために用いられます。これは、複数のJSファイルを一つにまとめるプロセスで、ネットワークリクエストの数を削減し、アプリケーションの読み込み時間を短縮する効果があります。
しかし、バンドルのサイズが大きくなると、読み込み時間が長くなり、パフォーマンスが低下する可能性があります。この問題を解決するために、チャンク戦略という考え方があります。
チャンク戦略とは
チャンク戦略は、JSのバンドルを複数の小さなファイル(チャンク)に分割することで、アプリケーションの読み込み時間を最適化する手法です。これにより、ユーザーが必要とするコードのみをダウンロードし、実行することが可能になります。
要は特に何も戦略を考えないでバンドルしたらプロジェクトのJSファイルが最終的には一つのファイルにまとめられるのに対し、JSのチャンク戦略を図ることでそれらを細かいパーツに分割して最適化を図るというイメージですね。
チャンクの種類
チャンクにはその役割に応じて、いくつか種類があります。
エントリーチャンク
アプリケーションのエントリーポイントであるJavaScriptファイル。これらは、アプリケーションの起動時に読み込まれます。
ベンダーチャンク
サードパーティのライブラリやフレームワークなど、外部の依存関係を含むチャンクです。これらは、アプリケーション全体で共通して使用されるため、別のチャンクとして分割されます。
例えばプロジェクトのアニメーションのライブラリとしてAnime.jsを使用する場合などはチャンク戦略を図った後、Anime.jsのスクリプトはベンダーチャンクの一つとして分割されます。
非同期チャンク
遅延読み込みやコードスプリッティングを利用して、非同期的に読み込まれるチャンクです。ユーザーが特定の機能にアクセスする際にのみ、読み込まれます。
最近話題になってきているAstroの主な機能であるAstroアイランド(ハイドレーション)はこの非同期チャンクの仕組みを使ったいい例ですね。
チャンク戦略の主な利点
パフォーマンスの最適化
必要なコードのみをダウンロードし、実行することで、読み込み時間が短縮され、パフォーマンスが向上します。
キャッシュの効率化
チャンクごとにキャッシュすることができるため、ユーザーが再訪問した際に、変更されていないチャンクを再ダウンロードする必要がなくなります。
ビルド時間の短縮
チャンク戦略によるビルド時間の短縮は、変更されたコードだけを再ビルドし、キャッシュから未変更のチャンクを再利用することができます。これにより、全体のビルド処理が高速化が期待できます。
SplitVendorChunkPluginを活用してViteプロジェクトを効率化する
Viteには、JSバンドルのチャンク戦略を図ることができるプラグインとしてSplitVendorChunkPluginというものがあります。このプラグインを使用すると、Vite環境でビルド時にベンダーチャンクを分割することができ、ブラウザキャッシュの効率化、ページ読み込み時間の短縮、ビルド時間の短縮といったメリットを享受できます。
実際に使ってみる
チャンク戦略なしで一旦実装
とりあえず公式通りにviteのプロジェクトを立ち上げたら、今回はこのプロジェクトにAnime.jsを入れてみます。
pnpm install animejs --save
そしてプロジェクトのルートにあるmain.jsを以下に書き換えて、anime.jsで何かを動かすコードを書いてみます。
import anime from 'animejs';
anime({
targets: '#target',
translateX: 250,
translateY: 250,
rotate: 180,
borderRadius: '50%',
easing: 'easeInOutQuad',
duration: 2000,
});
ここでビルドしてみましょう。
pnpm build
するとdist配下に以下のようなディレクトリ構成でビルドされると思います。
.
├── assets
│ └── index-9b6ef555.js
├── index.html
└── vite.svg
ここでビルドされたindex-9b6ef555.js
には先ほど自分で書いたコード+Anime.jsのコードが全て含まれています。
SplitVendorChunkPluginを使ってみる
プロジェクトのルートにvite.config.jsを作成して以下の設定を入れます。
import { splitVendorChunkPlugin, defineConfig } from 'vite';
export default defineConfig({
build: {
rollupOptions: {
output: {
chunkFileNames: 'assets/js/vendor/[hash].js',
entryFileNames: 'assets/js/[name].js',
},
},
},
plugins: [splitVendorChunkPlugin()],
});
build.rollupOptions.output.chunkFileNames
はチャンク戦略によって分割されたチャンクファイルのビルド先とそのファイル名を指定します。
build.rollupOptions.output.entryFileNames
は先ほどのチャンクの種類で説明したエントリーチャンクとなるJSファイルのビルド先とそのファイル名を指定します。
splitVendorChunkPlugin自体はimportで読み込んできてplugins
の配列に関数として記述するだけで使えます。新たに何かpnpm install
する必要はありません。
この設定で再度ビルドしてみると、以下のようにファイルが生成されます。
dist/
├── assets
│ └── js
│ ├── index.js
│ └── vendor
│ └── de4e5aa0.js
├── index.html
└── vite.svg
assets/js/vendor/de4e5aa0.js
はチャンク戦略によって分割されたチャンクファイルです。
各ファイルの中身としては、assets/js/index.js
の中身は自分で書いたコードとvendorディレクトリにあるAnime.jsのスクリプトを読み込むコードが書かれており、assets/js/vendor/de4e5aa0.js
はAnime.jsのコードが入っていて、自分で書いたコードとサードパーティライブラリのAnime.jsのコードを分割することができました。
といった流れで、viteでは簡単にチャンク戦略を実行することができます。
なぜViteにデフォルトで設定されていないのか?
SplitVendorChunkPluginを入れると一見メリットしかないのに、なぜわざわざ自分で追加でimportしなければならないのでしょうか?
公式にもその旨の記載があります。
ViteをSPAで使う分にはこのチャンク戦略は最適かもしれないですが、ViteはSPA以外でも使えるので、そういったユースケースを全て考慮するとデフォルトでチャンク戦略を有効にするのはちょっと...という意図があるみたいです。
おとなしく自分のプロジェクトで入れた方がいいなと思ったら入れましょう笑
SplitVendorChunkPluginのユースケース
ではここで、SplitVendorChunkPluginの具体的なユースケースを紹介します。
大規模プロジェクト
大規模プロジェクトでは、ビルド時間が非常に長くなることがあります。SplitVendorChunkPluginを使用することで、ビルド時間の短縮やブラウザキャッシュの効率化が期待できます。
サードパーティライブラリの利用
プロジェクトで多くのサードパーティライブラリを利用している場合、これらのライブラリがすべて1つのバンドルにまとめられると、ページの読み込み時間が長くなります。SplitVendorChunkPluginを使用することで、ライブラリのチャンクを分割し、ブラウザキャッシュの効率化が期待できます。
まとめ
以上、あまり知られていない?ViteのSplitVendorChunkPluginのお話でした。
このプラグインを導入することで、ブラウザキャッシュの効率化やページ読み込み時間の短縮、ビルド時間の短縮など、プロジェクトの特性によっては今の開発体験やアプリケーションのパフォーマンスをさらに向上させることができるかもしれませんね。
大きめのプロジェクトや多くのサードパーティライブラリを利用しているプロジェクトでは、ぜひ使ってみてはどうでしょうか〜
Discussion