Vite 8 Complete Guide: Rolldown, Oxc, and 10x Faster Builds (2026)
Build times in modern frontend development fell off a cliff in March 2026. Vite 8 shipped with Rolldown - a Rust-based bundler that replaces both esbuild and Rollup, runs the same Vite plugin API, and cuts production build times by 10-30x in real-world projects. Linear's build went from 46 seconds to 6. GitLab's shrank by 7x. This guide covers Vite 8 from initial setup to production optimization: what the new Rust toolchain actually changes, Full Bundle Mode, TypeScript path resolution without plugins, and migrating from Vite 6 or 7.
What Vite Does
Vite solves two different problems with two different strategies.
Development: No bundling. Vite serves files over native ES modules directly to the browser on-demand. Dev server startup is sub-300ms regardless of project size.
Production: Full bundling. Vite produces an optimized bundle - tree-shaken, code-split, minified. Previously this used esbuild for transforms and Rollup for bundling, which meant slightly different behavior between dev and prod. Vite 8 solves that with a single unified Rust toolchain.
What Changed in Vite 8
Vite 8 replaces the dual-tool production pipeline:
- Rolldown (bundler) replaces Rollup
- Oxc (parser, transformer, minifier) replaces esbuild
- Both are Rust-based, from the VoidZero team
- Single toolchain = identical dev and prod semantics
Installation
# New project
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
npm run dev
# Existing project
npm install --save-dev vite@latest @vitejs/plugin-react@latest
Vite 8 requires Node.js 20.0.0 or higher.
vite.config.ts Anatomy
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [
react(), // @vitejs/plugin-react v6 - Oxc-based, no Babel
],
resolve: {
// New in Vite 8: native TypeScript path alias resolution
tsconfigPaths: true,
},
server: {
port: 3000,
open: true,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
build: {
outDir: 'dist',
sourcemap: true,
rollupOptions: {
// Rolldown-compatible - most Rollup options work as-is
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
router: ['react-router-dom'],
},
},
},
},
})
The Rust Toolchain: Rolldown + Oxc
Rolldown
Rolldown is not just Rollup rewritten in Rust - it's designed from scratch with Vite's use case in mind:
- 10-30x faster on real projects
- Module-level persistent caching - only re-bundles what changed
- Full Bundle Mode (see below)
- Module Federation support built-in
- Better chunk splitting
The existing rollupOptions in your config works. There's a compatibility layer that auto-converts esbuild and Rollup configuration to Rolldown equivalents. For most projects, upgrading requires zero config changes.
Oxc
Oxc is the parser and transformer Rolldown uses internally. In Vite 8 it handles TypeScript stripping, JSX transform, minification, and tree-shaking - all faster than esbuild.
The impact on @vitejs/plugin-react v6:
# Vite 7 - requires Babel
@vitejs/plugin-react โ @babel/core + plugins (~45MB)
# Vite 8 - Oxc-based
@vitejs/plugin-react@6 โ no Babel (~8MB)
If you had custom Babel config in plugin-react, find the Oxc or Vite plugin equivalent:
// Vite 7 - Babel custom plugins
react({
babel: {
plugins: ['babel-plugin-styled-components']
}
})
// Vite 8 - Babel is gone; use Vite plugin equivalents
react()
// For styled-components: use @vitejs/plugin-oxc-styled-components
Full Bundle Mode
New in Vite 8 - bundles during development too:
export default defineConfig({
dev: {
bundleMode: true,
},
})
Results on large projects:
- 3x faster dev server startup
- 40% faster full reloads
- 10x fewer network requests
- Dev and prod behavior identical
For small projects (under ~100 modules), unbundled mode is still faster. Full Bundle Mode's benefits become significant at medium-to-large scale. HMR continues to work - only the affected module chunk is invalidated.
TypeScript Paths Without Plugins
Previously you needed vite-tsconfig-paths. Vite 8 reads your tsconfig.json natively:
// vite.config.ts
export default defineConfig({
resolve: {
tsconfigPaths: true, // reads paths from tsconfig.json
},
})
// tsconfig.json - these paths now work without any plugin
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@components/*": ["./src/components/*"],
"@hooks/*": ["./src/hooks/*"]
}
}
}
Uninstall vite-tsconfig-paths - it's no longer needed.
Environment Variables
# .env
VITE_API_URL=https://api.example.com
# Variables without VITE_ prefix are NOT exposed to the browser
// In your code
const apiUrl = import.meta.env.VITE_API_URL
const isDev = import.meta.env.DEV // boolean
const isProd = import.meta.env.PROD // boolean
TypeScript types for env variables (vite-env.d.ts):
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_API_URL: string
readonly VITE_APP_NAME: string
}
interface ImportMeta {
readonly env: ImportMetaEnv
}
Build Optimization
Code Splitting
build: {
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
if (id.includes('react')) return 'react-vendor'
if (id.includes('@tanstack')) return 'tanstack-vendor'
if (id.includes('recharts') || id.includes('d3')) return 'chart-vendor'
return 'vendor'
}
},
},
},
},
Bundle Analysis
npm install --save-dev rollup-plugin-visualizer
import { visualizer } from 'rollup-plugin-visualizer'
export default defineConfig({
plugins: [
react(),
visualizer({
open: true,
gzipSize: true,
}),
],
})
Run npm run build - opens an interactive treemap of your bundle.
Library Mode
Building a package for npm:
import { resolve } from 'path'
import { defineConfig } from 'vite'
import dts from 'vite-plugin-dts'
export default defineConfig({
plugins: [dts({ include: ['src'] })],
build: {
lib: {
entry: resolve(__dirname, 'src/index.ts'),
name: 'MyLib',
formats: ['es', 'cjs'],
fileName: (format) => `my-lib.${format}.js`,
},
rollupOptions: {
external: ['react', 'react-dom'],
},
},
})
package.json exports:
{
"main": "./dist/my-lib.cjs.js",
"module": "./dist/my-lib.es.js",
"exports": {
".": {
"import": "./dist/my-lib.es.js",
"require": "./dist/my-lib.cjs.js"
}
},
"types": "./dist/index.d.ts"
}
Migration from Vite 6 or 7
For the majority of projects:
npm install vite@latest @vitejs/plugin-react@latest
npm run build
That's it. The Rolldown compatibility layer handles the rest. If your build passes, you're done.
What to check manually:
// 1. Remove vite-tsconfig-paths
// Before:
import tsconfigPaths from 'vite-tsconfig-paths'
plugins: [react(), tsconfigPaths()]
// After:
resolve: { tsconfigPaths: true }
// 2. Remove Babel config from plugin-react (if any)
// Before:
react({ babel: { plugins: ['babel-plugin-X'] } })
// After: find the Oxc/Vite equivalent
// 3. Node.js version - Vite 8 requires Node.js 20+
// Update CI/CD if using Node.js 18
// 4. Check custom plugins using Rollup-only APIs
// Run npm run build and check for deprecation warnings
With Vitest
Vite 8 and Vitest share the same config file:
/// <reference types="vitest" />
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
resolve: { tsconfigPaths: true },
test: {
environment: 'jsdom',
setupFiles: ['./src/test/setup.ts'],
globals: true,
coverage: {
provider: 'v8',
reporter: ['text', 'html'],
},
},
})
Quick Reference
# Create project
npm create vite@latest my-app -- --template react-ts
# Dev server
vite # start
vite --port 4000 # custom port
vite --host # expose to network
# Build
vite build # production build
vite preview # preview prod build locally
// Minimal vite.config.ts (Vite 8)
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
resolve: { tsconfigPaths: true },
dev: { bundleMode: true }, // enable for large projects
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
},
},
},
},
})
Why It Matters
The numbers are real: 87% build time reductions aren't marketing. A 46-second build becoming 6 seconds changes how you work - you stop avoiding rebuilds, run more experiments, ship faster. More importantly, the dev/prod parity problem is solved. Years of "works in dev, breaks in prod" bugs traced to esbuild/Rollup differences are gone. One toolchain, one behavior.
Full article at stacknotice.com/blog/vite-complete-guide-2026
Comments
No comments yet. Start the discussion.