
A step-by-step account of upgrading a production Vue app to Vite 8 and Rolldown, the config changes that broke, and the actual build numbers before and after.
Reza Baar
July 8, 2026
Vite 8 shipped stable on March 12, 2026, with Rolldown, a Rust-based bundler, replacing both esbuild and Rollup. The announcement posts quote big numbers (Linear went from 46 seconds to 6 seconds), but those come from very large codebases. In this post, we'll migrate a real mid-size Vue app, measure the build before and after, and walk through the three config changes that actually broke. The goal is to give you a realistic picture, not the headline benchmark.
The project is a Vue 3 admin dashboard: about 180 components, Vue Router, Pinia, a charting library, and a UI component library. It was running Vite 7 with a standard config. This is the kind of project where you'd expect solid but not dramatic gains, which makes it a useful baseline.
Here's the starting vite.config.ts:
// vite.config.ts (Vite 7)
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router', 'pinia'],
charts: ['chart.js'],
},
},
},
},
});
Before changing anything, let's get a clean baseline. Run the production build a few times and take the median:
# Clear any cached build artifacts first
rm -rf dist node_modules/.vite
# Time the production build
time npm run build
On Vite 7, the median production build for this app was 11.4 seconds locally. Worth noting: local numbers understate the real gain. CI runners have slower disks and less CPU cache, which is exactly where a single-pass Rust bundler pulls further ahead. Keep that in mind when you see your own local number.
The Vite team recommends a gradual migration for anything beyond a trivial project. Instead of jumping straight to Vite 8, you first swap in the rolldown-vite package while staying on the Vite 7 API. This isolates Rolldown-specific issues from the other Vite 8 changes.
Step one: try rolldown-vite on your current setup. Add an override to your package.json:
{
"overrides": {
"vite": "npm:rolldown-vite@latest"
}
}
For pnpm, use the pnpm.overrides key instead. For Yarn, use resolutions. Then reinstall and run your build:
npm install
npm run build
If your build passes here, you know Rolldown itself is compatible with your project. If something breaks, you've narrowed it to the bundler swap rather than the full version jump.
Step two: upgrade to Vite 8 proper. Remove the override and install Vite 8 directly:
npm install vite@8 @vitejs/plugin-vue@latest
Vite 8 requires Node.js 20.19+ or 22.12+. The package is now ESM-only, and the install is a bit heavier (roughly 15 MB more) because you're pulling in Rolldown and Lightning CSS as native binaries.
For this app, three things needed fixing. Your mileage will vary, but these are the most common.
This was the first error on build. Rolldown doesn't support the object form of manualChunks, only the function form:
// Before: object syntax (breaks on Rolldown)
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'vue-router', 'pinia'],
charts: ['chart.js'],
},
},
},
}
// After: function syntax (works)
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules/vue')) return 'vendor';
if (id.includes('node_modules/chart.js')) return 'charts';
},
},
},
}
The build still worked with rollupOptions, but the terminal printed a deprecation warning. The option is renamed to rolldownOptions:
// Deprecated (still works, but warns)
build: {
rollupOptions: { /* ... */ }
}
// Preferred
build: {
rolldownOptions: { /* ... */ }
}
The same applies to worker.rollupOptions, which becomes worker.rolldownOptions. These aliases are deprecated now and will be removed in a future version, so it's worth updating them during the migration rather than later.
This is the one that's harder to spot because it can pass the build and fail at runtime. Rolldown handles ambiguous default imports from CommonJS modules differently than Rollup did. If you import a default export from a CJS package and it comes through as undefined, this is why.
The fix is usually to correct the import, but if you have many affected packages and need a temporary bridge, there's an escape hatch:
// vite.config.ts
export default defineConfig({
plugins: [vue()],
legacy: {
// Temporary: restores the old CJS interop behavior
inconsistentCjsInterop: true,
},
});
Treat this as a stopgap. The right long-term fix is to report the affected package to its author (link them to Rolldown's CJS interop docs) or correct the import in your own code.
Here's the cleaned-up config after all three fixes:
// vite.config.ts (Vite 8)
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
build: {
rolldownOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules/vue')) return 'vendor';
if (id.includes('node_modules/chart.js')) return 'charts';
},
},
},
},
});
After the migration, the same production build (again, median of several runs after clearing the cache):
That's about 3.7x faster locally. On our CI pipeline, where the Vite 7 build averaged 34 seconds, Vite 8 came in at 7 seconds, close to a 5x improvement. The CI gain being larger than the local gain matches what other teams have reported, and it's the number that actually matters day to day since CI runs on every push.
To be clear about expectations: this is a mid-size app, so it lands in the 3-5x range. Small projects (under 100 modules) tend to see 2-5x. Very large codebases (500+ modules) are where the 10-30x figures come from. The bundler benchmark of 19,000 modules finishing in 1.61 seconds versus Rollup's 40 seconds is real, but it's a synthetic bundler test, not a full app build. Don't expect the headline multiplier on a small app.
The build time is the headline, but the structural win is dev/prod consistency. On Vite 7, dev used esbuild and production used Rollup. Those two bundlers resolved modules and handled side-effect timing slightly differently, which produced a specific class of bug: code that worked in npm run dev but broke in the production build.
With Rolldown handling both, dev and production run the same engine. That entire category of "works on my machine, breaks in prod" issues largely goes away. For a team, this is arguably worth more than the seconds saved, because those bugs were the ones that slipped through to staging and cost real debugging time.
Based on this migration, here's a reasonable rule of thumb:
manualChunks conversion, and any CJS interop corrections. It's one focused piece of work rather than a scattered effort.If you're on Nuxt, you get Rolldown through Nuxt's Vite dependency, so the same benefits apply once your Nuxt version pulls in Vite 8.
rolldown-vite on Vite 7 first, then upgrade to Vite 8manualChunks object syntax, the rollupOptions to rolldownOptions rename, and CJS interopWe migrated a real mid-size Vue app to Vite 8, hit three config issues, fixed them in an afternoon, and cut local builds from 11.4 to 3.1 seconds (and CI builds by about 5x). The speed is nice, but the quieter win is that dev and production now behave identically. If you're on Vite 7, this is a low-risk, high-value upgrade.
I hope this post has been helpful. Happy coding!
Get the latest news and updates on developer certifications. Content is updated regularly, so please make sure to bookmark this page or sign up to get the latest content directly in your inbox.

Cache Components in Next.js
Cache Components is the Next.js 16 caching model behind Instant Navigations. Learn use cache, cacheLife, and cacheTag, and why data is dynamic by default.
Aurora Scharff
Jul 9, 2026

Migrating to Vite 8 + Rolldown
A step-by-step account of upgrading a production Vue app to Vite 8 and Rolldown, the config changes that broke, and the actual build numbers before and after.
Reza Baar
Jul 8, 2026

JavaScript Set Methods: Native Set Theory, Finally
Seven new methods landed on JavaScript's Set: union, intersection, difference, and more. Baseline since 2024. A practical guide with real-world examples.
Martin Ferret
Jul 7, 2026