| | |

Vite 21 ⚡ Rolldown — The Rust-based bundler replacing Rollup

⏱️ Estimated read: 11 min | |

Vite’s build pipeline was split across two bundlers for most of its history. esbuild handled the fast transforms during development, and Rollup handled the production bundle with its plugin ecosystem. The split worked, but it meant two transformation pipelines, two plugin systems, and a growing layer of glue code to keep the two aligned. Rolldown is the resolution: a single Rust-based bundler that replaces both, matches esbuild’s speed, and keeps Rollup’s plugin API so the ecosystem does not have to be rewritten .

The swap is not a drop-in replacement of one dependency with another. It changes what Vite is underneath. With Rolldown, Vite becomes the entry point to an end-to-end toolchain maintained by the same team: Vite for orchestration, Rolldown for bundling, and Oxc for parsing, transforming, and minifying . The alignment is the point. A single toolchain can adopt new language features faster and optimize across layers in ways the dual-bundler setup could not.

Key point: Rolldown replaces Rollup (production) and esbuild (development transforms) with a single Rust bundler. It keeps the Rollup plugin API, runs 10–30× faster than Rollup, and is the default in Vite 8 and later. The migration is mostly transparent for standard Vite projects, but the underlying options are renamed and some edge cases behave differently.


Why the dual-bundler setup was replaced

The consistency problem. esbuild and Rollup handle modules differently. A change that fixes an edge case in one pipeline risks introducing a difference in the other. The Vite team described the accumulated glue code as a growing tax: every alignment fix in development created a risk of divergence in production, and the two systems drifted slowly apart over years of feature additions .

The performance ceiling. Rollup is written in JavaScript, and its performance is bounded by the language runtime. Rolldown is written in Rust and runs at native speed. The benchmarks place it 10–30× faster than Rollup and on par with esbuild . The gap widens as project size grows, which is why the largest projects reported the largest gains: Linear’s production build dropped from 46 seconds to 6 seconds, Ramp saw a 57% reduction, and Beehiiv saw 64% .

The unified toolchain opportunity. Rolldown uses Oxc for parsing, resolving, transforming, and minifying. Because Vite, Rolldown, and Oxc are maintained by the same team (VoidZero), the layers can coordinate in ways that separate projects cannot. Oxc’s semantic analysis, for example, can feed Rolldown’s tree-shaking, which produces smaller bundles than Rollup’s syntax-only analysis could .

The trade-off. Vite 8’s install size is approximately 15 MB larger than Vite 7, with about 5 MB from the Rolldown binary and 10 MB from lightningcss becoming a normal dependency instead of an optional peer . The install cost is the price of the faster builds and the unified toolchain.


a. The migration surface and the renamed options

The configuration API and plugin hooks are deliberately kept stable. Most Vite plugins work unchanged because Rolldown supports the Rollup plugin API . The changes are in the option names and the underlying minifier, not in the shape of the configuration.

// vite.config.ts — the renamed options
import { defineConfig } from 'vite';

export default defineConfig({
  build: {
    // rollupOptions is renamed to rolldownOptions.
    // The old name is auto-converted with a deprecation warning.
    rolldownOptions: {
      external: ['vue'],
      output: { globals: { vue: 'Vue' } },
    },
  },
  // The esbuild option is renamed to oxc.
  // The old name is auto-converted.
  oxc: {
    jsx: {
      runtime: 'automatic',
      importSource: 'react',
    },
  },
});

The auto-conversion means existing configurations continue to work, but the deprecated names will be removed in a future major version . The build.rollupOptions alias maps to build.rolldownOptions, the esbuild option maps to oxc, and optimizeDeps.esbuildOptions maps to optimizeDeps.rolldownOptions . The migration is a rename, not a rewrite, for the common case.

The minification behavior changes independently of the option names. JavaScript minification now uses Oxc instead of esbuild by default, and CSS minification uses Lightning CSS . The Oxc minifier makes slightly different assumptions about source code than esbuild, and property mangling options (mangleProps, reserveProps) are not supported . A project that relied on esbuild-specific minification behavior must either accept the Oxc defaults or install esbuild as a dev dependency and use the deprecated build.minify: 'esbuild' fallback .


b. The behavior changes that surface in production

Most projects will not notice the bundler swap. The ones that do are the ones that depend on edge-case behavior that Rollup and esbuild implemented differently. The Vite migration guide documents the specific cases.

// The CommonJS interop change.
// The default import from a CJS module now behaves consistently
// across development and build, but the behavior is different
// from what some projects relied on previously.
import pkg from 'some-cjs-package';
// The default import is now module.exports if:
// - the importer is .mjs/.mts
// - the importer's package.json has "type": "module"
// - module.exports.__esModule is not true
// Otherwise it is module.exports.default.

// The legacy behavior can be restored temporarily:
export default defineConfig({
  legacy: {
    inconsistentCjsInterop: true,
  },
});

The CommonJS interop change is the most likely source of a production-only failure, because the behavior was previously inconsistent between development and build . A package that worked in development but failed in production (or the reverse) may now behave consistently, but consistently in the way that the project did not expect. The legacy.inconsistentCjsInterop option is the escape hatch, and it is deprecated.

The module resolution behavior also changes when a package.json contains both browser and module fields. Vite used to sniff the file format to decide which field to use; Rolldown uses the modern resolution rules . A package that relied on the sniffing behavior may resolve to a different file than it did before.


Complete Example Session

// ============================================
// PART 1: THE DEFAULT VITE 8 CONFIGURATION
// ============================================

// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  // No bundler configuration needed.
  // Rolldown is the default.
  // The build command uses it automatically.
});

// ============================================
// PART 2: THE RENAMED BUILD OPTIONS
// ============================================

// vite.config.ts — with rolldownOptions
export default defineConfig({
  build: {
    // The old name was rollupOptions.
    // The new name is rolldownOptions.
    rolldownOptions: {
      external: ['react', 'react-dom'],
    },
  },
});

// ============================================
// PART 3: THE RENAMED TRANSFORM OPTIONS
// ============================================

// vite.config.ts — with oxc
export default defineConfig({
  // The old name was esbuild.
  oxc: {
    jsx: {
      runtime: 'automatic',
      importSource: 'react',
    },
  },
});

// ============================================
// PART 4: THE MINIFICATION CHANGE
// ============================================

// JavaScript minification uses Oxc by default.
// CSS minification uses Lightning CSS by default.
export default defineConfig({
  build: {
    // The default minifier is 'oxc'.
    // The 'esbuild' fallback requires esbuild as a dev dependency.
    minify: 'oxc',
  },
});

// ============================================
// PART 5: THE COMMONJS INTEROP CHANGE
// ============================================

// The default import from a CJS module behaves consistently.
// If the project relied on the old inconsistent behavior:
export default defineConfig({
  legacy: {
    // Restores the old behavior temporarily.
    // Deprecated; will be removed in a future major.
    inconsistentCjsInterop: true,
  },
});

// ============================================
// PART 6: THE PLUGIN COMPATIBILITY
// ============================================

// Most Vite plugins work unchanged.
// The plugin API is the Rollup plugin API.
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    // A plugin written for Rollup or Vite.
    // It works with Rolldown without modification.
  ],
});

// ============================================
// PART 7: THE PERFORMANCE VERIFICATION
// ============================================

// Run the build and compare the time.
// A large project should see a measurable reduction.
//
// Before: 45s (Rollup)
// After:  12s (Rolldown)
//
// The reduction is proportional to the project size.
// The largest projects see the largest gains.

// ============================================
// PART 8: THE MIGRATION PATH
// ============================================

// Path 1: Direct upgrade.
// Update vite to 8.x in package.json.
// Run the build. Fix any option renames.
//
// Path 2: Gradual migration (recommended for large projects).
// 1. Install rolldown-vite.
// 2. Run the build and identify incompatibilities.
// 3. Fix the issues.
// 4. Upgrade to Vite 8.

// ============================================
// PART 9: THE FULL BUNDLE MODE (EXPERIMENTAL)
// ============================================

// Rolldown unlocks an experimental full bundle mode.
// It bundles modules during development, similar to production.
// Preliminary results: 3x faster dev server startup,
// 40% faster full reloads, 10x fewer network requests.
export default defineConfig({
  experimental: {
    // The full bundle mode is experimental.
    // It changes the dev server behavior.
  },
});

// ============================================
// PART 10: THE VERIFICATION CHECKLIST
// ============================================

// [ ] The Vite version is 8.x or later.
// [ ] The rollupOptions are renamed to rolldownOptions.
// [ ] The esbuild option is renamed to oxc.
// [ ] The minification behavior is verified (Oxc vs esbuild).
// [ ] The CommonJS interop is tested in production.
// [ ] The build time is measured against the previous version.
// [ ] The plugins are verified against Rolldown.

The ten parts covered the default configuration, the renamed options, the minification change, the CommonJS interop change, the plugin compatibility, the performance verification, the migration paths, and the experimental full bundle mode. The through-line is that the migration is mostly a rename, and the behavior changes are specific and documented.


Quick Reference

The option renames

Vite 7Vite 8
build.rollupOptionsbuild.rolldownOptions
worker.rollupOptionsworker.rolldownOptions
optimizeDeps.esbuildOptionsoptimizeDeps.rolldownOptions
esbuildoxc

The minifier defaults

LanguageVite 7Vite 8
JavaScriptesbuildOxc
CSSesbuildLightning CSS

The performance gains

CompanyBeforeAfterReduction
Linear46s6s87%
Ramp——57%
Mercedes-Benz.io——38%
Beehiiv——64%

The behavior changes

ChangeImpactEscape hatch
CommonJS interopDefault import behaviorlegacy.inconsistentCjsInterop
Module resolutionbrowser/module field precedence—
MinificationOxc vs esbuild assumptionsbuild.minify: 'esbuild'

Best Practices

✅ Do This:

// Use the new option names
build: { rolldownOptions: { external: ['vue'] } }               // ✅

// Use the oxc option for transforms
oxc: { jsx: { runtime: 'automatic' } }                          // ✅

// Test the production build after the upgrade
npm run build                                                    // ✅

// Use the gradual migration path for large projects
// rolldown-vite → Vite 8                                        // ✅

❌ Don’t Do This:

// Rely on the deprecated names indefinitely
build: { rollupOptions: {} } // auto-converted, will be removed // ❌

// Assume the CommonJS interop is unchanged
// The behavior is different; test the production build          // ❌

// Use property mangling with Oxc
// Oxc does not support mangleProps                               // ❌

Common Pitfalls

PitfallWhy It HappensFix
Build fails after upgradeA plugin relies on a Rollup-specific behaviorCheck the plugin’s Rolldown compatibility
Production behavior differsThe CommonJS interop changedTest with legacy.inconsistentCjsInterop
Minification breaks codeOxc makes different assumptionsCompare with esbuild minifier or report the issue
Option is ignoredThe deprecated name was usedRename to rolldownOptions or oxc
Install size increasedRolldown binary and lightningcssExpected; the trade-off for faster builds

Real-World Examples

1. Rename rollupOptions

build: { rolldownOptions: { external: ['vue'] } }

2. Rename esbuild to oxc

oxc: { jsx: { runtime: 'automatic' } }

3. Oxc minifier

build: { minify: 'oxc' }

4. esbuild fallback

build: { minify: 'esbuild' } // requires esbuild devDependency

5. CommonJS escape hatch

legacy: { inconsistentCjsInterop: true }

6. Gradual migration

npm install -D rolldown-vite

7. Direct upgrade

npm install -D vite@8

8. Plugin compatibility

plugins: [legacyPlugin()] // works if it follows the Rollup API

9. Performance measurement

time npm run build

10. Full bundle mode

experimental: { /* full bundle mode */ }

Visual

The Dual-Bundler vs Unified Toolchain

┌──────────────────────────────────────────────────────────────┐
│  VITE 7 VS VITE 8                                             │
│                                                              │
│  Vite 7 (dual bundler)        Vite 8 (unified)              │
│  ┌─────────────────────┐     ┌─────────────────────┐        │
│  │ Dev: esbuild        │     │ Dev: Oxc + Rolldown │        │
│  │ Prod: Rollup        │     │ Prod: Rolldown      │        │
│  │                     │     │                     │        │
│  │ Two pipelines       │     │ One pipeline        │        │
│  │ Two plugin systems  │     │ One plugin API      │        │
│  │ Glue code           │     │ Unified behavior    │        │
│  └─────────────────────┘     └─────────────────────┘        │
│                                                              │
│  The unification removes the inconsistency between          │
│  development and production.                                │
└──────────────────────────────────────────────────────────────┘

The Performance Gap

┌──────────────────────────────────────────────────────────────┐
│  BUILD TIME                                                  │
│                                                              │
│  Rollup (JS)          ████████████████████████████████       │
│  Rolldown (Rust)      ████████                               │
│                                                              │
│  10–30× faster. The gap widens as the project grows.        │
│                                                              │
│  Linear: 46s → 6s                                           │
│  Ramp:   57% reduction                                      │
│  Beehiiv: 64% reduction                                     │
└──────────────────────────────────────────────────────────────┘

The Migration Path

┌──────────────────────────────────────────────────────────────┐
│  TWO PATHS                                                   │
│                                                              │
│  Direct upgrade              Gradual migration              │
│  ┌─────────────────────┐    ┌─────────────────────┐         │
│  │ vite@8              │    │ 1. rolldown-vite     │         │
│  │                     │    │ 2. Test              │         │
│  │ Fix option renames  │    │ 3. Fix issues        │         │
│  │ Test the build      │    │ 4. vite@8            │         │
│  └─────────────────────┘    └─────────────────────┘         │
│                                                              │
│  The gradual path isolates the bundler change               │
│  from the Vite upgrade.                                     │
└──────────────────────────────────────────────────────────────┘

Summary

ItemValue
RolldownRust-based bundler replacing Rollup and esbuild
Speed vs Rollup10–30× faster
Plugin compatibilityRollup plugin API
Option renamerollupOptions → rolldownOptions
Transform optionesbuild → oxc
JS minifierOxc (was esbuild)
CSS minifierLightning CSS (was esbuild)
Vite 8 defaultRolldown
Install size~15 MB larger (Rolldown + lightningcss)

Key takeaways:

  • Rolldown replaces both esbuild and Rollup. The dual-bundler setup is gone. Development transforms use Oxc, and production bundling uses Rolldown. The unified pipeline removes the inconsistency between development and production behavior .
  • The Rollup plugin API is preserved. Most Vite plugins work unchanged. The plugin ecosystem does not need to be rewritten, which is what makes the migration practical for existing projects .
  • The option names are the migration surface. rollupOptions becomes rolldownOptions, and esbuild becomes oxc. The old names are auto-converted with deprecation warnings, so the migration is a rename, not a rewrite .
  • The minifiers changed. JavaScript uses Oxc, and CSS uses Lightning CSS. The Oxc minifier makes different assumptions than esbuild, and property mangling is not supported. A project that relied on esbuild-specific minification behavior must verify its output .
  • The CommonJS interop is the behavior change most likely to surface. The default import from a CJS module now behaves consistently, but the consistent behavior is different from what some projects relied on. The legacy.inconsistentCjsInterop option is the temporary escape hatch .

Remember: Rolldown is the bundler that unifies Vite’s toolchain. It replaces the esbuild-plus-Rollup split with a single Rust bundler that is fast, Rollup-compatible, and coordinated with Oxc. The migration is mostly transparent: the plugins work, the configuration is renamed, and the build gets faster. The edge cases are in the behavior that the dual-bundler setup masked: the CommonJS interop, the module resolution, and the minifier assumptions. Test the production build, verify the output, and use the escape hatches if the project depends on the old behavior.

Was this helpful?


Stop using slow, ad-bloated tool sites! 🤮

🔎 Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)

⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free

🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!