Vite has been the default build tool for React, Vue, and most modern frontend frameworks for years. But it always had an architectural split: esbuild for development transforms, Rollup for production bundling. Two different tools with different behaviors, different plugin APIs, and occasional inconsistencies between dev and prod. Vite 8 closes this gap. Rolldown, the Rust-based bundler built specifically for Vite, replaces both esbuild and Rollup as the single engine powering every stage of the pipeline. The result is faster builds, consistent behavior, and a simpler mental model.
Rolldown: one bundler for everything
Previous versions of Vite used esbuild to transform TypeScript and JSX during development, and Rollup to bundle everything for production. This worked, but the two tools had different treeshaking algorithms, different module resolution, and different edge cases around circular dependencies. Bugs that only appeared in production builds were the most frustrating kind.
Rolldown eliminates this entirely. Written in Rust, it handles both the dev transform pipeline and production bundling with the same engine.
# Dev server startup on a large project
vite 7 (esbuild): 1.8s
vite 8 (rolldown): 0.6s
# Production build
vite 7 (rollup): 28s
vite 8 (rolldown): 9s
The speed gains come from Rust’s native performance and from removing the overhead of coordinating between two separate tools. But the bigger win is consistency: what works in dev works in prod. No more “it bundles fine locally but breaks in CI.”
Backward-compatible by default
Rolldown implements Rollup’s plugin API. Existing Vite plugins that use Rollup hooks continue to work without changes.
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
});
The configuration is identical to previous versions. No new plugin format to learn, no migration step for standard projects. The switch to Rolldown is internal. If your project uses only official plugins and standard configuration, the upgrade is a version bump in package.json.
For plugins that relied on Rollup-specific internals or undocumented behavior, Vite 8 provides a compatibility layer that logs warnings for deprecated patterns. The migration path is gradual, not a cliff.
OXC-powered transforms
Vite 8 uses OXC (Oxidation Compiler) for TypeScript and JSX transforms. OXC is a Rust-based toolchain that handles parsing, transforming, and linting JavaScript and TypeScript at native speed.
export default defineConfig({
oxc: {
target: 'es2022',
jsxImportSource: 'react',
},
});
TypeScript stripping, JSX transformation, and syntax downleveling all happen in a single Rust pass. No more separate esbuild step for transforms followed by a Rollup step for bundling. One pipeline, one set of source maps, one configuration surface.
The practical impact is most visible in HMR. Module updates that previously went through esbuild’s transform, then Vite’s module graph, now go through a single Rolldown + OXC pipeline. HMR updates on large projects land in under 20ms consistently.
Environment API: first-class SSR
Vite 8 stabilizes the Environment API introduced in Vite 6. Each environment (client, server, edge) has its own module graph, resolve conditions, and optimization settings.
export default defineConfig({
environments: {
client: {
build: {
outDir: 'dist/client',
rollupOptions: {
input: './src/entry-client.tsx',
},
},
},
ssr: {
build: {
outDir: 'dist/server',
rollupOptions: {
input: './src/entry-server.tsx',
},
},
resolve: {
conditions: ['node'],
},
},
},
});
Before the Environment API, SSR builds used the same config as client builds with awkward overrides. Server-only packages leaked into the client bundle, and client-only code crashed on the server. Each environment now has isolated resolution, so import 'fs' in a server environment resolves correctly while the client environment ignores it entirely.
Frameworks like Next.js, Remix, and SolidStart use this API internally. For application developers, the benefit is that framework-level SSR works more reliably without manual ssr.external or ssr.noExternal configuration.
Improved chunk splitting
Rolldown’s treeshaking and chunk splitting are more aggressive than Rollup’s. It produces fewer and smaller chunks by default, with better deduplication of shared modules.
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
ui: ['@radix-ui/react-dialog', '@radix-ui/react-popover'],
},
},
},
},
});
Manual chunk configuration still works for explicit control, but the defaults are better. Rolldown automatically identifies shared dependencies across dynamic imports and splits them into separate chunks that load in parallel. A common pattern where three lazy routes all import the same charting library no longer produces three copies of that library in three separate chunks.
The output also includes better scope hoisting. Modules that are only imported once are inlined into their parent chunk, reducing the number of function wrappers and improving runtime performance.
Faster dependency pre-bundling
Vite pre-bundles dependencies on first run to convert CommonJS packages to ESM and reduce the number of HTTP requests during development. Rolldown handles this step natively, making cold starts significantly faster.
# First run pre-bundling (500+ dependencies)
vite 7 (esbuild): 4.2s
vite 8 (rolldown): 1.8s
The pre-bundled output is also more consistent. Rolldown resolves and bundles dependencies using the same algorithm it uses for application code, eliminating a class of bugs where pre-bundled dependencies behaved differently from production-bundled ones.
For monorepos with shared packages, Rolldown correctly handles workspace dependencies without the optimizeDeps.include workarounds that were sometimes necessary with esbuild.
CSS improvements
Vite 8 brings Lightning CSS as the default CSS processor, replacing PostCSS for most transforms. Vendor prefixing, nesting, and syntax lowering happen without PostCSS plugins.
export default defineConfig({
css: {
lightningcss: {
targets: { chrome: 100, firefox: 100, safari: 16 },
},
},
});
CSS modules, @import resolution, and minification all go through Lightning CSS, which is orders of magnitude faster than PostCSS-based alternatives. Tailwind CSS v4 works natively without PostCSS since it integrates directly with Vite’s plugin system.
For projects that still need PostCSS (custom plugins, legacy transforms), it remains available as an opt-in. But for the majority of projects, Lightning CSS handles everything with zero configuration.
Migration from Vite 7
The upgrade path is intentionally smooth. Most projects need only a version bump.
{
"devDependencies": {
"vite": "^8.0.0",
"@vitejs/plugin-react": "^5.0.0"
}
}
Breaking changes are minimal. The key ones to watch for are removal of the legacy CJS Node.js API (use ESM imports), the define option now uses Rolldown semantics for string replacements, and the minimum Node.js version is 22. Custom Rollup plugins that access this.meta.rollupVersion will see a different value, but this rarely affects behavior.
Running npx vite --profile generates a build performance report that highlights any plugins adding latency to the pipeline, useful for identifying bottlenecks after upgrading.
Conclusion
Vite 8 is what Vite was always heading toward: a single, fast, Rust-powered pipeline from source to production. Rolldown eliminates the dev/prod split that caused subtle bugs. OXC handles transforms at native speed. The Environment API makes SSR a first-class concern. And the upgrade path respects existing configurations. For teams already on Vite, the upgrade is straightforward. For teams still on webpack, the performance gap just got wider.