- はじめに
- Viteアーキテクチャの進化:Rollup + esbuildからRolldownへ
- Rolldownの中核技術の分析
- Vite 8.0のインストールとマイグレーションガイド
- 比較表:フロントエンドビルドツールの対決
- フレームワーク別の設定例
- プラグイン互換性とマイグレーション戦略
- 性能最適化の詳細ガイド
- トラブルシューティングガイド
- 運用上の注意事項
- Rust ベースのビルドツールのエコシステム比較
- 性能の測定とモニタリング
- マイグレーションのチェックリスト
- おわりに
- 参考資料

はじめに
Vite 8.0がesbuildとRollupをRustベースのRolldownバンドラーに統合し、10~30倍のビルド性能向上を達成した。フロントエンドのビルドツールのエコシステムが、JavaScriptからRust/Goのネイティブツールへ移行する決定的な分岐点である。Turbopack、Rspackとともに、Rustベースのビルドツールによる三つ巴の構図が形成され、開発者の生産性革命が加速している。
本記事では、Vite 8.0のアーキテクチャの変化、Rolldownの中核技術、実践的なマイグレーション、そして競合ツールとの比較を掘り下げて扱う。
Viteアーキテクチャの進化:Rollup + esbuildからRolldownへ
既存のViteアーキテクチャが抱えた二重エンジン問題
Vite 7.xまでのアーキテクチャは、二つの異なるエンジンに依存していた。
Vite 7.x アーキテクチャ:
開発サーバー (Dev) 本番ビルド (Build)
+------------------+ +------------------+
| esbuild (Go) | | Rollup (JS) |
| - 事前バンドル | | - バンドリング |
| - TypeScript変換 | | - ツリーシェイク |
| - JSX変換 | | - コード分割 |
+------------------+ +------------------+
| |
v v
ネイティブESM提供 最適化バンドル出力
この構造には根本的な問題があった。
- 開発とプロダクションの不一致: esbuildとRollupの動作の違いにより、開発環境では問題のなかったコードがプロダクションビルドで壊れるケースが発生
- プラグインの二重管理: esbuildプラグインとRollupプラグインを別々に管理する必要がある
- プロダクションビルド速度の限界: RollupがJavaScriptで書かれているため、大規模プロジェクトではビルド時間が分単位
Vite 8.0の統合エンジン:Rolldown
Evan Youが率いるVoidZeroチームは、この問題を根本的に解決するためにRolldownを開発した。RolldownはRollupのAPIをRustで再実装したバンドラーであり、Vite 8.0で唯一のバンドリングエンジンとなる。
Vite 8.0 アーキテクチャ:
開発サーバー (Dev) + 本番ビルド (Build)
+----------------------------------+
| Rolldown (Rust) |
| - 依存の事前バンドル |
| - TypeScript/JSX変換 |
| - バンドリング |
| - ツリーシェイキング |
| - コード分割 |
| - ソースマップ生成 |
+----------------------------------+
| |
v v
ネイティブESM提供 最適化バンドル出力
主な利点は以下のとおりである。
- 単一エンジン: 開発とプロダクションが同一のエンジンを使うため不一致が解消
- Rustネイティブの速度: esbuild(Go)水準のパース速度とRollup水準の最適化品質
- Rollupプラグイン互換: 既存のRollupプラグインの大半をそのまま使用可能
Rolldownの中核技術の分析
Rustベースのバンドリングエンジン
Rolldown(GitHub: rolldown/rolldown)はSWC(RustベースのTypeScript/JavaScriptコンパイラ)をパーサーとして使い、独自のモジュールグラフ構築と最適化パイプラインを実装している。
Rolldown 内部パイプライン:
1. パース (SWC)
- TypeScript -> AST
- JSX -> AST
- 並列パース (Rayon 活用)
2. モジュール解決 (Module Resolution)
- Node.js 互換の解決アルゴリズム
- package.json exports 対応
- 条件付き export の処理
3. モジュールグラフの構築
- 依存関係グラフの分析
- 循環依存の検出
- サイドエフェクトの分析
4. 最適化
- ツリーシェイキング (使用されない export の削除)
- スコープホイスティング (モジュールのマージ)
- コード分割 (動的 import ベース)
- 共通チャンクの抽出
5. コード生成
- 圧縮 (minification)
- ソースマップ生成
- アセットのハッシュ付与
性能の秘密:並列処理
Rolldownが既存のRollupより速い中核的な理由は、Rustの並列処理能力にある。
// Rolldown 並列パースの概念 (簡略化した擬似コード)
// 実際の実装は rolldown/rolldown GitHub で確認
use rayon::prelude::*;
use std::path::PathBuf;
struct ModuleInfo {
path: PathBuf,
ast: swc_ecma_ast::Module,
imports: Vec<String>,
exports: Vec<String>,
}
fn parse_modules_parallel(entry_files: Vec<PathBuf>) -> Vec<ModuleInfo> {
// Rayon を使った並列パース
// 各ファイルを独立にパースして CPU コアを最大限に活用
entry_files
.par_iter()
.map(|file| {
let source = std::fs::read_to_string(file).unwrap();
let ast = swc_parse(&source);
let (imports, exports) = analyze_module(&ast);
ModuleInfo {
path: file.clone(),
ast,
imports,
exports,
}
})
.collect()
}
fn tree_shake_parallel(modules: &mut Vec<ModuleInfo>) {
// ツリーシェイキングもモジュール単位で並列処理
modules.par_iter_mut().for_each(|module| {
remove_unused_exports(module);
});
}
JavaScriptベースのRollupはシングルスレッドで動作するためファイルを順次処理するが、RolldownはパースとツリーシェイキングをCPUコア数だけ並列に実行する。
Vite 8.0のインストールとマイグレーションガイド
新規プロジェクトの作成
# Vite 8.0 の新規プロジェクト作成
npm create vite@latest my-app -- --template react-ts
# または pnpm を使用 (推奨)
pnpm create vite my-app --template react-ts
# 対応テンプレート:
# vanilla, vanilla-ts
# react, react-ts, react-swc, react-swc-ts
# vue, vue-ts
# svelte, svelte-ts
# preact, preact-ts
# lit, lit-ts
# solid, solid-ts
# qwik, qwik-ts
cd my-app
pnpm install
pnpm dev
Vite 7から8へのマイグレーション
# 1. Vite のアップグレード
pnpm add -D vite@^8.0.0
# 2. 関連プラグインのアップグレード
pnpm add -D @vitejs/plugin-react@latest
# または SWC プラグイン
pnpm add -D @vitejs/plugin-react-swc@latest
# 3. 不要になったパッケージの削除
# esbuild は Rolldown に置き換えられるため個別インストールは不要
# (Vite が内部で管理)
# 4. 互換性の確認
npx vite --version
# vite/8.0.x
vite.config.ts のマイグレーション
// vite.config.ts (Vite 8.0)
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
export default defineConfig({
plugins: [react()],
// Rolldown 関連の新しい設定
build: {
// Rolldown が既定のバンドラーとして設定される (明示は不要)
// ビルドターゲットの設定
target: 'es2022',
// コード分割の戦略
rollupOptions: {
output: {
// Rollup API 互換 - 既存設定の大半を維持できる
manualChunks: {
vendor: ['react', 'react-dom'],
router: ['react-router-dom'],
},
},
},
// 新しい Vite 8 の最適化オプション
cssMinify: 'lightningcss', // Lightning CSS を既定でサポート
minify: 'oxc', // OXC ベースの圧縮 (任意)
// ソースマップの設定
sourcemap: true,
},
// 開発サーバーの設定
server: {
port: 3000,
// HMR が Rolldown に統合された
hmr: {
overlay: true,
},
},
// 依存関係の最適化 (既存の esbuild -> Rolldown へ自動移行)
optimizeDeps: {
include: ['react', 'react-dom', 'react-router-dom'],
// esbuildOptions はもう使用しない
// 代わりに rolldownOptions を使用
},
// CSS の設定
css: {
// Lightning CSS が PostCSS の代替として既定でサポートされる
transformer: 'lightningcss',
lightningcss: {
targets: {
chrome: 100,
firefox: 100,
safari: 15,
},
},
},
})
主な Breaking Changes
// ===== Breaking Change 1: esbuildOptions の削除 =====
// Vite 7 (以前)
// export default defineConfig({
// optimizeDeps: {
// esbuildOptions: {
// target: 'es2020',
// define: { global: 'globalThis' },
// },
// },
// })
// Vite 8 (以降)
export default defineConfig({
optimizeDeps: {
// Rolldown ベースで自動的に最適化
// 大半の esbuildOptions はもう不要
},
// グローバル定義は define オプションを使用
define: {
global: 'globalThis',
},
})
// ===== Breaking Change 2: CSS 処理の変更 =====
// Vite 7: PostCSS が既定
// Vite 8: Lightning CSS が既定、PostCSS も対応
// postcss.config.js があれば自動的に PostCSS を使用
// Lightning CSS を使うには postcss.config.js を削除するか:
export default defineConfig({
css: {
transformer: 'lightningcss', // 明示的な設定
},
})
// ===== Breaking Change 3: Node.js の最小バージョン =====
// Vite 8 は Node.js 20.0.0 以上が必要
// package.json に engines フィールドの追加を推奨
// "engines": {
// "node": ">=20.0.0"
// }
比較表:フロントエンドビルドツールの対決
Vite 8 vs Vite 7 vs webpack vs Turbopack vs Rspack
| 特性 | Vite 8 (Rolldown) | Vite 7 (Rollup+esbuild) | webpack 5 | Turbopack | Rspack |
|---|---|---|---|---|---|
| 中核言語 | Rust | JS + Go | JavaScript | Rust | Rust |
| バンドラーエンジン | Rolldown | Rollup | webpack | Turbopack | Rspack |
| 開発サーバー | ESM + Rolldown | ESM + esbuild | DevServer | Turbo DevServer | DevServer |
| コールドスタート | 極めて速い | 非常に速い | 遅い | 速い | 速い |
| HMR 速度 | 極めて速い | 非常に速い | 普通 | 速い | 速い |
| プロダクションビルド | 非常に速い | 普通 | 遅い | (開発中) | 速い |
| ツリーシェイキング | 優秀 | 優秀 | 普通 | 普通 | 普通 |
| コード分割 | 優秀 | 優秀 | 優秀 | 普通 | 優秀 |
| プラグインのエコシステム | Rollup 互換 | Rollup | webpack | 限定的 | webpack 互換 |
| フレームワーク対応 | React/Vue/Svelte+ | React/Vue/Svelte+ | すべて | Next.js 専用 | React/Vue |
| 設定の複雑さ | 低い | 低い | 高い | 低い | 中間 |
| 安定性 (2026.03) | 安定 | 非常に安定 | 非常に安定 | ベータ | 安定 |
ビルド時間のベンチマーク
大規模な React プロジェクト(1000+ コンポーネント、500+ ルート)を基準としたベンチマークである。
| ツール | コールドビルド | ウォームビルド | HMR (単一ファイル) | メモリ使用量 |
|---|---|---|---|---|
| Vite 8.0 (Rolldown) | 2.1s | 0.8s | 12ms | 380MB |
| Vite 7.x (Rollup) | 28.4s | 12.3s | 45ms | 1.2GB |
| webpack 5 | 45.2s | 8.7s | 320ms | 2.1GB |
| Rspack 1.x | 3.8s | 1.2s | 35ms | 520MB |
| Turbopack (beta) | 3.2s | 0.9s | 18ms | 450MB |
Vite 8.0 は Vite 7.x 比で コールドビルド 13.5 倍、HMR 3.75 倍 速い。これは Rust ネイティブエンジンと並列処理の直接的な結果である。
フレームワーク別の設定例
React + TypeScript プロジェクト
// vite.config.ts - React プロジェクト
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import tsconfigPaths from 'vite-tsconfig-paths'
export default defineConfig({
plugins: [
react({
// SWC ベースの React 変換 (Rolldown 内蔵の SWC を活用)
jsxImportSource: '@emotion/react',
}),
tsconfigPaths(),
],
build: {
target: 'es2022',
rollupOptions: {
output: {
manualChunks(id) {
// ベンダーチャンクの分離戦略
if (id.includes('node_modules')) {
if (id.includes('react') || id.includes('react-dom')) {
return 'react-vendor'
}
if (id.includes('@tanstack')) {
return 'tanstack-vendor'
}
if (id.includes('lodash') || id.includes('date-fns')) {
return 'utils-vendor'
}
return 'vendor'
}
},
},
},
// チャンクサイズ警告のしきい値
chunkSizeWarningLimit: 500, // KB
},
// 環境変数の接頭辞
envPrefix: 'VITE_',
// パスのエイリアス
resolve: {
alias: {
'@': '/src',
'@components': '/src/components',
'@hooks': '/src/hooks',
'@utils': '/src/utils',
},
},
})
Vue 3 プロジェクト
// vite.config.ts - Vue プロジェクト
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import Components from 'unplugin-vue-components/vite'
import AutoImport from 'unplugin-auto-import/vite'
export default defineConfig({
plugins: [
vue({
script: {
defineModel: true,
propsDestructure: true,
},
}),
vueJsx(),
Components({
// コンポーネントの自動インポート
dirs: ['src/components'],
dts: true,
}),
AutoImport({
imports: ['vue', 'vue-router', 'pinia'],
dts: true,
}),
],
build: {
target: 'es2022',
cssMinify: 'lightningcss',
},
css: {
preprocessorOptions: {
scss: {
additionalData: '@use "@/styles/variables" as *;',
},
},
},
})
Svelte 5 プロジェクト
// vite.config.ts - Svelte プロジェクト
import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'
export default defineConfig({
plugins: [
svelte({
// Svelte 5 の runes モード
compilerOptions: {
runes: true,
},
}),
],
build: {
target: 'es2022',
rollupOptions: {
output: {
// Svelte はコンパイラの特性上、小さなバンドルを生成
manualChunks: undefined, // 自動分割に委ねる
},
},
},
})
プラグイン互換性とマイグレーション戦略
Rollup プラグイン互換性マトリクス
プラグイン互換性 (Vite 8.0 基準):
完全互換 (すぐに使用可能):
- @rollup/plugin-alias
- @rollup/plugin-json
- @rollup/plugin-replace
- @rollup/plugin-yaml
- @rollup/plugin-image
- rollup-plugin-visualizer
部分互換 (設定の修正が必要):
- @rollup/plugin-commonjs (Rolldown 内蔵の CJS 変換の使用を推奨)
- @rollup/plugin-node-resolve (Rolldown 内蔵のリゾルバの使用を推奨)
- @rollup/plugin-terser (Rolldown 内蔵の圧縮器の使用を推奨)
非互換 (代替が必要):
- rollup-plugin-esbuild -> 不要 (Rolldown が SWC を内蔵)
- @rollup/plugin-babel -> SWC で代替
- rollup-plugin-postcss -> Lightning CSS または Vite 内蔵の CSS 処理
カスタムプラグインのマイグレーション
// Vite 7 のプラグイン (Rollup 互換)
// -> Vite 8 でも大半がそのまま動作
import type { Plugin } from 'vite'
function myCustomPlugin(): Plugin {
return {
name: 'my-custom-plugin',
// Rollup 互換フック (Vite 8 でもそのまま動作)
resolveId(source) {
if (source === 'virtual:my-module') {
return source
}
return null
},
load(id) {
if (id === 'virtual:my-module') {
return 'export const version = "1.0.0"'
}
return null
},
transform(code, id) {
if (id.endsWith('.custom')) {
// カスタムファイル形式の変換
return {
code: transformCustomFormat(code),
map: null,
}
}
},
// Vite 専用フック (Vite 8 で動作)
configureServer(server) {
server.middlewares.use('/api', (req, res, next) => {
// 開発サーバーのミドルウェア
next()
})
},
}
}
function transformCustomFormat(code: string): string {
// カスタム変換ロジック
return `export default ${JSON.stringify(code)}`
}
ビルド分析プラグインの活用
// vite.config.ts - ビルド分析の設定
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import { visualizer } from 'rollup-plugin-visualizer'
export default defineConfig(({ mode }) => ({
plugins: [
react(),
// ビルド分析 (プロダクションビルドのみ)
mode === 'production' &&
visualizer({
open: true,
filename: 'dist/stats.html',
gzipSize: true,
brotliSize: true,
}),
].filter(Boolean),
build: {
// ビルドレポートの生成
reportCompressedSize: true,
rollupOptions: {
output: {
// アセットのファイル名パターン
assetFileNames: 'assets/[name]-[hash][extname]',
chunkFileNames: 'js/[name]-[hash].js',
entryFileNames: 'js/[name]-[hash].js',
},
},
},
}))
性能最適化の詳細ガイド
依存関係の事前バンドリングの最適化
// vite.config.ts - 依存関係の最適化
export default defineConfig({
optimizeDeps: {
// 頻繁に使う依存関係をあらかじめバンドリング
include: [
'react',
'react-dom',
'react-router-dom',
'@tanstack/react-query',
'axios',
'date-fns',
'lodash-es',
],
// バンドリングから除外するパッケージ
exclude: [
// ESM で直接提供されるパッケージ
'@vueuse/core',
],
// Vite 8: 依存関係のキャッシュが Rolldown に統合された
// キャッシュの位置: node_modules/.vite/rolldown
},
})
大規模プロジェクトのビルド最適化
// vite.config.ts - 大規模プロジェクトの最適化
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
export default defineConfig({
plugins: [react()],
build: {
target: 'es2022',
// マルチページビルドの設定
rollupOptions: {
input: {
main: 'src/main.tsx',
admin: 'src/admin.tsx',
},
output: {
manualChunks(id) {
// 細かなチャンク分割
if (id.includes('node_modules')) {
// フレームワークのコア
if (id.includes('react') || id.includes('react-dom')) {
return 'framework'
}
// UI ライブラリ
if (id.includes('@radix-ui') || id.includes('@headlessui')) {
return 'ui-lib'
}
// 状態管理
if (id.includes('zustand') || id.includes('@tanstack')) {
return 'state'
}
// ユーティリティ
if (id.includes('lodash') || id.includes('date-fns')) {
return 'utils'
}
// 残りのベンダー
return 'vendor'
}
// 共通コンポーネント
if (id.includes('src/components/common')) {
return 'common-components'
}
},
},
},
// 圧縮の設定
minify: 'terser', // または 'oxc' (Vite 8 の新規オプション)
terserOptions: {
compress: {
drop_console: true, // プロダクションで console.log を削除
drop_debugger: true,
},
},
// CSS のコード分割
cssCodeSplit: true,
},
})
HMR 性能の最大化
// vite.config.ts - HMR の最適化
export default defineConfig({
server: {
hmr: {
// WebSocket オーバーレイの設定
overlay: true,
// HMR ポート (プロキシ環境で有用)
// port: 24678,
},
// ファイル監視の最適化
watch: {
// 大規模プロジェクトで性能が向上
// chokidar の usePolling は既定で false (イベントベースの監視)
usePolling: false,
// 無視するパス
ignored: ['**/node_modules/**', '**/.git/**', '**/dist/**', '**/coverage/**'],
},
},
// Vite 8: Rolldown の増分ビルドを活用
// 変更されたモジュールだけを再バンドリングして HMR 速度を最大化
})
トラブルシューティングガイド
よくあるマイグレーションの問題と解決策
| 症状 | 原因 | 解決策 |
|---|---|---|
Cannot find module エラー | Rolldown のモジュール解決の違い | resolve.alias を明示的に設定 |
| CSS スタイルの崩れ | Lightning CSS が既定に変更 | css.transformer: 'postcss' を設定 |
| HMR が動作しない | プラグインの非互換 | プラグインの最新バージョンを確認 |
| ビルド出力サイズの増加 | ツリーシェイキングの違い | sideEffects フィールドを確認 |
| TypeScript エラー | SWC 変換の違い | tsconfig.json の設定を確認 |
| 環境変数が認識されない | import.meta.env の変更 | VITE_ 接頭辞を確認 |
CommonJS モジュールの互換性問題
// 問題: CJS モジュールが ESM に変換されない場合
// vite.config.ts で明示的に処理
export default defineConfig({
optimizeDeps: {
// CJS モジュールを強制的に事前バンドリングに含める
include: ['problematic-cjs-package'],
},
build: {
// CommonJS 検出の設定
commonjsOptions: {
// 変換するファイルのパターン
include: [/node_modules/],
// strict モードでの CJS 変換
strictRequires: true,
},
},
})
ソースマップのデバッグ問題
// ソースマップ設定ガイド
export default defineConfig(({ mode }) => ({
build: {
// 開発: インラインソースマップ (高速なマッピング)
// ステージング: 別ファイルのソースマップ
// プロダクション: hidden ソースマップ (エラーレポート用のみ)
sourcemap: mode === 'development' ? 'inline' : mode === 'staging' ? true : 'hidden',
},
// CSS のソースマップ
css: {
devSourcemap: true,
},
}))
メモリ関連の問題
# 大規模プロジェクトで OOM が発生した場合
# Node.js のヒープメモリを拡張
NODE_OPTIONS="--max-old-space-size=8192" pnpm build
# Vite 8 は Rolldown(Rust) がネイティブメモリを使用するため
# Node.js のヒープとは別にシステムメモリの確認が必要
# 最小推奨: ビルド対象ファイル数 x 0.5MB
# メモリ使用量のモニタリング
NODE_OPTIONS="--max-old-space-size=8192 --trace-gc" pnpm build 2>&1 | grep "GC"
運用上の注意事項
CI/CD パイプラインの設定
# .github/workflows/build.yml
name: Build and Deploy
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
# Vite 8 のビルドキャッシュを活用
- name: Cache Vite build
uses: actions/cache@v4
with:
path: |
node_modules/.vite
node_modules/.cache
key: vite-build-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: |
vite-build-
- name: Build
run: pnpm build
env:
NODE_ENV: production
- name: Type Check
run: pnpm tsc --noEmit
- name: Lint
run: pnpm lint
# ビルドサイズのレポート
- name: Report bundle size
run: |
echo "## Bundle Size Report" >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
du -sh dist/assets/* | sort -rh >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
Docker ビルドの最適化
# Dockerfile - Vite 8 のプロダクションビルド
# Stage 1: ビルド
FROM node:20-slim AS builder
RUN corepack enable pnpm
WORKDIR /app
# 依存関係のキャッシュレイヤー
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
# ソースのコピーとビルド
COPY . .
RUN pnpm build
# Stage 2: サービング
FROM nginx:alpine
# nginx の設定
COPY nginx.conf /etc/nginx/conf.d/default.conf
# ビルド成果物のみコピー
COPY /app/dist /usr/share/nginx/html
# SPA ルーティングのための設定を含む
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# nginx.conf - SPA ルーティングとアセットのキャッシュ
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# ハッシュ付きアセットは長期キャッシュ
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
try_files $uri =404;
}
# HTML は常に最新バージョンを提供
location / {
try_files $uri $uri/ /index.html;
add_header Cache-Control "no-cache";
}
# gzip 圧縮
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml;
gzip_min_length 1000;
}
環境別のビルド戦略
// vite.config.ts - 環境別の分岐
import { defineConfig, loadEnv } from 'vite'
import react from '@vitejs/plugin-react-swc'
export default defineConfig(({ mode }) => {
// 環境変数の読み込み
const env = loadEnv(mode, process.cwd(), '')
return {
plugins: [react()],
// 環境別のビルド設定
build: {
// 開発: 高速なビルドを優先
// プロダクション: 最適化を優先
minify: mode === 'production' ? 'terser' : false,
sourcemap: mode === 'production' ? 'hidden' : true,
rollupOptions: {
output: {
// プロダクションでのみチャンク分割
...(mode === 'production' && {
manualChunks: {
vendor: ['react', 'react-dom'],
},
}),
},
},
},
// API プロキシ (開発環境)
server: {
proxy: {
'/api': {
target: env.VITE_API_URL || 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
// 環境変数の定義
define: {
__APP_VERSION__: JSON.stringify(process.env.npm_package_version),
__BUILD_TIME__: JSON.stringify(new Date().toISOString()),
},
}
})
Rust ベースのビルドツールのエコシステム比較
Rust 3 大バンドラーの詳細比較
Rolldown (Vite 8)
- 目標: Rollup + esbuild の統合的な置き換え
- 強み: Vite エコシステムとの統合、Rollup プラグイン互換
- 弱み: 初期バージョン、検証期間が必要
- 適合: Vite ユーザー、汎用プロジェクト
Turbopack (Next.js)
- 目標: webpack の置き換え (Next.js 専用)
- 強み: Next.js に最適化、Vercel のサポート
- 弱み: Next.js 以外での使用は限定的
- 適合: Next.js プロジェクト
Rspack (独立)
- 目標: webpack のドロップイン置き換え
- 強み: webpack 互換性が最高、マイグレーションが容易
- 弱み: webpack のレガシー設計を踏襲
- 適合: webpack から移行する大規模プロジェクト
フレームワークとビルドツールのマッチングガイド
| フレームワーク | 推奨ビルドツール | 理由 |
|---|---|---|
| React (SPA) | Vite 8 | 最高の性能、汎用性 |
| React (SSR) | Vite 8 または Next.js (Turbopack) | SSR 要件に応じて |
| Vue 3 | Vite 8 | 公式推奨、最適な統合 |
| Svelte/SvelteKit | Vite 8 | SvelteKit の公式バンドラー |
| Next.js | Turbopack | 公式バンドラー、最適な統合 |
| 大規模レガシー (webpack) | Rspack | webpack.config を再利用できる |
| Remix | Vite 8 | Remix v3 から Vite ベース |
| Astro | Vite 8 | 公式バンドラー |
性能の測定とモニタリング
ビルド性能の測定スクリプト
#!/bin/bash
# build-benchmark.sh - ビルド性能の比較スクリプト
echo "=== Vite 8 ビルドベンチマーク ==="
# キャッシュのクリア (コールドビルド)
rm -rf node_modules/.vite dist
# コールドビルドの測定
echo "--- Cold Build ---"
time pnpm build 2>&1
# ウォームビルドの測定 (キャッシュあり)
echo "--- Warm Build ---"
time pnpm build 2>&1
# ビルド結果の分析
echo "--- Build Output ---"
du -sh dist/
echo "--- Asset Sizes ---"
du -sh dist/assets/* | sort -rh | head -20
# gzip 圧縮後のサイズ
echo "--- Gzipped Sizes ---"
for file in dist/assets/*.js; do
original=$(wc -c < "$file")
gzipped=$(gzip -c "$file" | wc -c)
echo "$file: ${original}B -> ${gzipped}B ($(( gzipped * 100 / original ))%)"
done
Lighthouse CI との統合
// lighthouserc.ts - Lighthouse CI の設定
export default {
ci: {
collect: {
startServerCommand: 'pnpm preview',
url: ['http://localhost:4173/'],
numberOfRuns: 3,
},
assert: {
assertions: {
'categories:performance': ['error', { minScore: 0.9 }],
'first-contentful-paint': ['warn', { maxNumericValue: 1500 }],
'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
'total-blocking-time': ['warn', { maxNumericValue: 200 }],
'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
},
},
upload: {
target: 'temporary-public-storage',
},
},
}
マイグレーションのチェックリスト
- Node.js のバージョンが 20.0.0 以上か
-
vite@^8.0.0と関連プラグインが最新バージョンか -
esbuildOptionsの設定を削除し、Rolldown 互換の設定に置き換えたか - CSS 処理が Lightning CSS への移行で壊れていないか
- すべての Rollup プラグインが Vite 8 と互換か
- CommonJS モジュールが正常に変換されるか
- ビルド成果物のサイズと構造が期待と一致するか
- HMR がすべてのファイルタイプで正常に動作するか
- CI/CD パイプラインが Vite 8 のビルドに対応しているか
- プロダクション環境でソースマップの設定が適切か
- 環境変数が正しく注入されるか
- ビルド性能のベンチマークを実施して改善を確認したか
おわりに
Vite 8.0 と Rolldown の登場は、フロントエンドビルドツールの歴史における重要な転換点である。esbuild と Rollup という二つの異なるエンジンに依存していた構造的な限界を Rust ベースの単一エンジンで解決し、10~30倍の性能向上と開発/プロダクションの一貫性を同時に達成した。
Turbopack が Next.js 専用という制約を持ち、Rspack が webpack 互換性に注力しているのに対し、Rolldown は汎用バンドラーとしてのポジショニングが明確である。Rollup の豊富なプラグインエコシステムを継承しながら Rust の性能を得たことは、強力な競争力である。
プロダクション導入にあたっては、プラグインの互換性検証、CSS 処理方式の変更、CommonJS モジュールの扱いなどを入念に確認する必要がある。ただし、ほとんどのプロジェクトではマイグレーションのコストに対して性能向上が圧倒的であるため、Vite を使用中のチームであれば 8.0 へのアップグレードを積極的に検討することを勧める。
参考資料
- Vite 8.0 Release Blog - 公式リリースノートおよびマイグレーションガイド
- Rolldown GitHub Repository - Rust ベースバンドラーのソースコードおよび技術ドキュメント
- Vite Official Documentation - Vite の設定、API、プラグインガイド
- Evan You - "Vite and the Rolldown Vision" - Vite/Rolldown アーキテクチャの発表
- Turbopack vs Rspack vs Rolldown Benchmarks - クロスバンドラーの性能比較