Viteはデフォルトで非常に高速ですが、アプリケーション規模の増大に伴い、本番ビルドのロールアップチャンク処理に時間がかかるようになります。manualChunks を使用したファイルサイズ分散化やキャッシュ戦略のベストプラクティスを共有します。
本記事では、フロントエンド開発の標準バンドラーとなったViteについて、本番ビルドの最適化、コード分割(Code Splitting)の微調整、および開発サーバーの応答性維持に役立つ高度な設定手法を解説します。
1. ビルド最適化の要:コード分割(Code Splitting)
Viteは本番環境のバンドルに Rollup を使用しています。コード分割を適切に行わないと、巨大な1つのJavaScriptファイル(単一チャンク)が出力されてしまい、初期ロード時間が悪化する原因になります。
1) ダイナミックインポート(Dynamic Imports)の活用
最も簡単なコード分割は、ルーターレベルでダイナミックインポートを使用することです。これにより、アクセスされたページに必要なJavaScriptだけがオンデマンドでロードされます。
// Reactでの遅延ロード例
import { lazy } from 'react';
const HeavyDashboard = lazy(() => import('./pages/Dashboard'));
2) manualChunks によるライブラリの分離
頻繁に変更されない外部ライブラリ(reactやlodash、chart.jsなど)は、アプリケーションのアプリケーションコードとは別の共通チャンク(vendor)に切り出すことで、ブラウザキャッシュの恩恵を最大化できます。
vite.config.js での設定例
import { defineConfig } from 'vite';
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks(id) {
// node_modules配下のパッケージを独立したチャンクに分割
if (id.includes('node_modules')) {
// パッケージ名ごとにさらに細分化する例
return id.toString().split('node_modules/')[1].split('/')[0].toString();
}
}
}
}
}
});
2. ビルド時間を短縮するためのコンパイラ調整
1) ミニファイアの選択(esbuild vs terser)
Viteはデフォルトで高速な esbuild をミニファイア(コード圧縮)として使用しています。より圧縮率を高めるために terser を指定することもできますが、ビルド時間は大幅に増大します。
速度重視のプロジェクトでは、常に minify: 'esbuild' を指定します。
2) ソースマップ(Source Maps)の無効化
開発中は便利なソースマップですが、本番ビルド時に生成すると膨大なメモリを消費し、ビルド時間を倍増させます。本番ビルドでソースマップが不要であれば、明示的に無効化しましょう。
// vite.config.js
export default defineConfig({
build: {
sourcemap: false // 本番環境での不要なソースマップ生成を停止
}
});
3. 開発体験(DX)の維持:依存関係の事前バインド(Dependency Pre-Bundling)
Viteは初回起動時に、node_modules 内の共通モジュール(CommonJS形式など)をブラウザで扱えるESモジュール(ESM)形式へ事前変換し、キャッシュします。
たまに、動的にロードされる依存関係が事前バインドから漏れてしまい、ページ遷移時にブラウザのリロードが突然発生する現象(フルリロード)が起きることがあります。これを防ぐために、あらかじめバインド対象を明記してビルドの無駄を排除します。
// vite.config.js
export default defineConfig({
optimizeDeps: {
include: ['my-heavy-library', 'chart.js'] // 事前にバインドを強制するパッケージを指定
}
});
4. まとめ:継続的なバンドル監査
ビルドチューニングで重要なのは、現在のバンドルサイズとチャンク構成を可視化することです。rollup-plugin-visualizer などのプラグインを導入し、どのライブラリがサイズを圧迫しているか、不要なコードが含まれていないかを定期的に確認し、常に高速な状態を維持しましょう。
