Vite の major update を見ると、まず build time を測りたくなります。
気持ちは分かる。Vite は速さで信頼を取ってきたツールだし、Rolldown が入るなら「何秒速くなったか」は気になる。
でも既存の production app を持っているなら、自分なら最初にそこは見ません。先に見るのは vite.config.*、plugin、chunk の切れ方です。
速くなるかどうかは最後でいい。移行初日の目的は「速くなった」と喜ぶことではなく、「今の repo が Rollup 時代の暗黙知にどれくらい寄っているか」を見つけることだと思っています。
まず Vite 依存を棚卸しする
最初にやることは地味です。
npm ls vite
npm ls @vitejs/plugin-react @vitejs/plugin-vue @vitejs/plugin-svelte
pnpm ならこうでもいいです。
pnpm why vite
pnpm why @vitejs/plugin-react
見るのは Vite 本体の version だけではありません。
- framework plugin
- unofficial plugin
- 社内や個人で書いた custom plugin
- test / storybook / docs 側が別に持っている Vite 依存
- monorepo の package ごとに違う Vite version
このへんを先に出します。
Vite app は、見た目より plugin に依存していることが多いです。React や Vue の公式 plugin だけならまだ読みやすいですが、Markdown、SVG、WASM、legacy build、PWA、Sentry upload、CSS 周りの plugin が混ざると、build が通るかどうかだけでは判断しづらくなります。
まずは config の危ない場所を拾います。
rg "rollupOptions|manualChunks|plugins|ssr|lib|worker|css" \
vite.config.* package.json
この時点で build.rollupOptions が厚い repo は、build time より先に互換性を見るべきです。
manualChunks を使っている repo は先に artifact を見る
個人的に一番見たいのはここです。
// vite.config.ts
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes("node_modules")) {
return "vendor";
}
},
},
},
},
});
こういう設定はよくあります。
悪いわけではありません。むしろ運用している app では、vendor split、route ごとの chunk、admin 画面だけ分ける、みたいな理由で手を入れていることが普通にあります。
ただ、ここは「build が成功した」だけでは足りないです。
見たいのは成果物です。
rm -rf dist
npm run build
find dist -type f | sort
du -sh dist
before / after を残しておくなら、雑にこうします。
rm -rf /tmp/vite-before /tmp/vite-after
npm run build
cp -R dist /tmp/vite-before
# Vite 8 / Rolldown 側へ更新したあと
npm run build
cp -R dist /tmp/vite-after
diff -ru /tmp/vite-before /tmp/vite-after | sed -n '1,160p'
diff -ru だと minified JS の中身までは見づらいですが、最初の確認としては十分です。
- chunk 数が急に増えていないか
- vendor chunk の名前が変わっていないか
- dynamic import の単位が変わっていないか
- CSS file の出方が変わっていないか
- asset file name の pattern が変わっていないか
- sourcemap が必要な形で出ているか
このあたりを先に見る。
特に CDN cache や error monitoring が file name に依存している場合、chunk name の変化は build time より実害があります。速くなったけど監視が読めない、みたいな移行は普通にしんどい。
plugin compatibility は「通った/落ちた」だけで見ない
plugin の確認も、単純な成功/失敗で終わらせない方がいいです。
Vite plugin は hook の順番、返り値、仮想 module、transform 対象、dev server と build の差に依存しがちです。
たとえば custom plugin があるなら、最低限このへんを探します。
rg "name:|resolveId|load\\(|transform\\(|generateBundle|writeBundle|configureServer" \
vite.config.* src tools scripts
見つかったら、plugin ごとに雑に分類します。
1. dev server 専用
2. build artifact を変える
3. asset / CSS / SVG を触る
4. virtual module を作る
5. bundle 後に upload や manifest 生成をする
一番注意したいのは 2 と 5 です。
dev server で動いたから大丈夫、は Vite 移行ではあまり信用しません。開発中の transform と production build の bundling は別の事故り方をします。
自分なら local でこういう順に見ます。
npm run build
npm run preview
preview を起動したら、最低限の route を踏みます。
- 初回表示
- lazy route
- dynamic import される重い画面
- CSS module / scoped CSS を使う画面
- SVG や worker を使う画面
- SSR があるなら server entry と client hydration
E2E がある repo なら、ここは人間がポチポチするより CI に寄せた方がいいです。
npm run build
npm run preview -- --host 127.0.0.1 &
npm run test:e2e
移行 PR で一番怖いのは、「build が通ったし速いので merge したが、特定 route だけ chunk load error になる」タイプです。これは release 後に気づくと面倒です。
vite.config.* の Rollup 依存を読む
Vite を長く使っている repo ほど、config に歴史が残ります。
たとえばこういうものです。
export default defineConfig({
build: {
sourcemap: true,
lib: {
entry: "src/index.ts",
formats: ["es", "cjs"],
},
rollupOptions: {
external: ["react", "react-dom"],
output: {
globals: {
react: "React",
},
},
},
},
});
library mode、SSR、worker、external、globals、manual chunks。
このへんは「Vite の設定」ではありますが、中身はかなり Rollup の理解に寄っています。Rolldown 前提で見直すなら、公式 migration guide を読むだけでなく、自分の config がどの層に依存しているのかを分けて読む方が早いです。
自分ならメモをこう作ります。
Vite native に近い設定
- server
- env
- resolve.alias
- css.modules
Rollup 境界に近い設定
- build.rollupOptions
- manualChunks
- external
- output.fileNames
- library mode
plugin 固有の設定
- framework plugin
- unofficial plugin
- custom plugin
この分類を PR description に貼るだけでも、レビューがかなり楽になります。
CI では「速度」より先に差分を保存する
速度を見るな、という話ではありません。
ただし、最初の CI で欲しいのは benchmark より差分です。
name: vite-migration-check
on:
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run build
- run: find dist -type f | sort > dist-files.txt
- run: du -sh dist | tee dist-size.txt
- uses: actions/upload-artifact@v4
with:
name: vite-dist-summary
path: |
dist-files.txt
dist-size.txt
これだけでも、reviewer が見られる情報は増えます。
もう少しちゃんとやるなら、main branch の artifact summary と比較します。大きい app では chunk graph を可視化してもいいですが、最初から凝る必要はないです。
大事なのは「速くなりました」ではなく、「何が変わったか」を PR に残すことです。
移行 PR に貼るチェックリスト
自分なら Vite 8 / Rolldown 移行 PR に、最低限このチェックリストを入れます。
## Vite 8 / Rolldown migration check
- [ ] `vite.config.*` の `build.rollupOptions` を読んだ
- [ ] `manualChunks` / chunk naming の差分を見た
- [ ] custom / unofficial plugin の build 結果を見た
- [ ] dynamic import される route を preview で確認した
- [ ] CSS splitting / asset file name の変化を確認した
- [ ] SSR / library mode / worker を使っているか確認した
- [ ] `dist/` の file list と size を PR に残した
- [ ] sourcemap と error stack の見え方を確認した
- [ ] CI cache の hit/miss と artifact size を見た
- [ ] 最後に build time を測った
最後に build time です。
ここが順番として大事だと思っています。速度改善は嬉しい。でも、速度は「正しく動く」ことの後に乗る価値です。
速度は最後に測ればいい
Vite 8 / Rolldown の移行で面白いのは、単に build が速くなることではありません。
bundler の前提が変わることで、今まで Rollup に寄せていた設定や plugin の癖が見えるところです。
小さい app なら、上げて build して終わりでも大丈夫かもしれません。けれど、長く運用している frontend repo では、config の中に過去の判断が溜まっています。manual chunk、SSR、library mode、unofficial plugin、CI artifact。こういうものは、速さの数字より先に見た方がいい。
自分なら移行初日はこう進めます。
npm ls vite
rg "rollupOptions|manualChunks|plugins|ssr|lib|worker" vite.config.* package.json
npm run build
find dist -type f | sort
npm run preview
そのあとに build time を測る。
Vite の major update は、毎回「速いらしい」で雑に触りたくなります。でも Rolldown 前提の移行では、まず自分の repo の依存関係と成果物を見る方が堅いです。
速さは最後にちゃんと喜べばいい。