Tech 10 min read

Vite 8.0 speeds up builds by up to 30x with Rolldown

IkesanContents

Vite 8.0 has been released. The biggest change this time was to abolish the esbuild used during development and the Rollup used for production builds, and to use the Rust bundler Rolldown. The long-standing problem of “bundle results being slightly different between the development environment and the production environment” is resolved at the architecture level.

Why the 2-bundler configuration was a problem

Until now, Vite had a hybrid configuration, using esbuild (fast but not compatible with all Rollup plugins) on the development server and Rollup (rich plugin ecosystem) on vite build. The difference in behavior between the two has become a breeding ground for bugs, and there has been no end to cases in which the software works in development but breaks in the production build.

Rolldown is a project created to solve this problem. Developed based on Rust and OXC (Oxidation Compiler), it achieves esbuil-like speed while maintaining compatibility with all Rollup plugin APIs.

Performance improvement track record

Up to 30 times faster performance has been reported in benchmarks, but results in actual projects are more convincing.

ProjectChange
Linear46 seconds → 6 seconds (87% reduction)
Ramp57% reduction
Mercedes-Benz.ioUp to 38% reduction
Beehiiv64% reduction

These are numbers reported by real users after transitioning to Rolldown. Although there are differences depending on the size of the project and the configuration of dependent libraries, improvements that can be felt are seen in many cases.

New features

Vite Devtools Integration Debugging and analysis tools can now be used with the devtools option. It incorporates functions that were previously supplemented by plug-ins, such as bundle configuration and module graph visualization.

TypeScript paths automatic resolution Built-in function to automatically convert paths settings of tsconfig.json to resolve.alias of Vite. Can be enabled with resolve.tsconfigPaths: true. Default is disabled.

emitDecoratorMetadata compatible External plugins are no longer required for frameworks that use experimentalDecorators and emitDecoratorMetadata, such as NestJS.

WebAssembly SSR support .wasm?initImport now works in SSR environment (on Node.js).

Browser console forwarding server.forwardConsole: true allows you to forward the browser console log to Vite’s development server terminal. Debugging in a multi-window configuration becomes easier.

@vitejs/plugin-react v6

The plugin for React was also majorly updated to v6 at the same time. The JSX conversion that previously relied on Babel has been switched to OXC-based, and there is no longer a need to separately install Babel. When using React compiler, use reactCompilerPreset helper.

Installation size

Vite 8 has an increase of approximately 15MB compared to Vite 7. The breakdown is lightningcss (~10MB) and Rolldown itself (~5MB). lightningcss contributes to improving the accuracy of CSS minimization and is not a simple bloat.

Node.js requirements

Same as Vite 7, requires Node.js 20.19+ or 22.12+.

How to migrate

Officials recommend a gradual transition.

  1. Test migration to rolldown-vite package in a project currently using Vite 7
  2. If there are no problems, upgrade to Vite 8

A compatibility layer is provided, so many projects can be upgraded without any configuration changes. However, it is necessary to check the operation of original settings and plugins that depend on esbuild.

npm install vite@8 --save-dev

Rolldown implements a rollup compatible API, so Rollup plugins will work almost as is. There are cases where an alternative to the esbuild plugin (via optimizeDeps.esbuildOptions, etc.) is required.

Future developments

Full Bundle Mode is planned as the next phase. This mode also performs bundling during development, and is expected to increase startup speed by three times. Current development servers deliver files individually for each module, but in large projects this can add up to thousands of requests, slowing things down. Full Bundle Mode solves this.

Other features such as access to raw AST and native MagicString conversion are also said to be in development, and the direction remains to bring the entire toolchain to Rust.

Internal architecture of Rolldown

Rolldown is often referred to as being made by Rust, but it’s actually quite well-crafted. Bundle processing consists of a three-stage pipeline: Scan → Link → Generate.

graph TD
    A[エントリーポイント] --> B[Scan Stage]
    B --> C[oxc_parserでAST生成]
    C --> D[AstScannerで<br/>import/export解析]
    D --> E[プラグインhook実行<br/>resolveId, load, transform]
    E --> F[Link Stage]
    F --> G[シンボル解決<br/>bind_imports_and_exports]
    G --> H[Tree Shaking<br/>include_statements]
    H --> I[CJS互換ラッパー注入<br/>wrap_modules]
    I --> J[Generate Stage]
    J --> K[チャンク生成<br/>generate_chunks]
    K --> L[Scope Hoisting<br/>AST最適化]
    L --> M[出力レンダリング<br/>コンテンツハッシュ付与]

In Scan Stage, ModuleLoader loads modules in parallel with tokio runtime. Each module is converted to AST by oxc_parser, and AstScanner blender import/export dependencies. Plugin resolveId, load, transform hooks are also executed at this stage.

The Link Stage resolves symbol references between all modules collected in the Scan Stage. bind_imports_and_exports() identifies which export satisfies which import, and include_statements() performs Tree Shaking to mark only reachable code. A runtime wrapper is injected into the CommonJS module with wrap_modules().

In the Generate Stage, generate_chunks() divides the module into chunks, and ScopeHoistingFinalizer performs AST optimization (variable hoisting, symbol renaming, removing unnecessary wrapper functions). Finally, a content hash is added and output to a file.

Parallelization is also used differently for each layer. Runtimes are selected according to processing characteristics: tokio (asynchronous I/O) for module loading, rayon (CPU-bound parallel) for chunk rendering, and worker threads for plugin execution.

Integration with OXC ecosystem

Rolldown relies heavily on OXC (Oxc v0.115.0). The parser, transformer, minifier, resolver, and source map generator are all composed of OXC components.

ComponentRole
oxc_parserAST generation from source code
oxc_transformerCode conversion (JSX, TypeScript, etc.)
oxc_minifierCompression of output
oxc_resolver v11.17.1Module resolution (yarn PnP compatible)
oxc_sourcemap v6.xSource map management

It is also exposed to the JavaScript side via NAPI-RS binding, and the compatibility layer with the Rollup plugin is also realized through this mechanism. Runtime helpers (__commonJSMin, __toESM, asyncToGenerator, etc.) are embedded as string constants and injected during module wrapping.

Breaking change details

From the official migration guide, we have extracted points that are easy to get into.

Changing configuration options

Options related to esbuild and rollup are automatically converted, but are deprecated.

Old optionNew optionNotes
optimizeDeps.esbuildOptionsoptimizeDeps.rolldownOptionsAutomatic conversion, will be deleted in the future
esbuildoxcJSX settings format is different
build.rollupOptionsbuild.rolldownOptionsAutomatic conversion, will be deleted in the future
build.minify: 'esbuild'build.minify: 'oxc'You can also use esbuild
build.cssMinifyDefault is Lightning CSSCan be changed back to esbuild

Please note that the format of the JSX settings has changed.

// Vite 7
esbuild: {
  jsx: 'automatic',
  define: { 'process.env.NODE_ENV': '"production"' }
}

// Vite 8
oxc: {
  jsx: { runtime: 'automatic' },
  define: { 'process.env.NODE_ENV': '"production"' }
}

Removed features

  • output.manualChunks object format → transition to codeSplitting option
  • esbuild.supported → No equivalent option for OXC
  • Replacing resolve.alias[].customResolverresolveId with a custom plugin with hooks
  • SystemJS/AMD output format → End of support
  • Plugin hooks such as shouldTransformCachedModule / resolveImportMeta → deleted

CommonJS compatibility changes

The easiest thing to get addicted to is the behavior change of CJS interop. In Rolldown, default As a result of unifying the handling of imports between development and production, there are cases where existing CJS module imports are broken.

// 以前は動いていたがVite 8で壊れる可能性がある
import something from 'cjs-package';
// → somethingがundefinedになる

// 一時的な回避策
// vite.config.ts
export default defineConfig({
  legacy: {
    inconsistentCjsInterop: true  // 非推奨、将来削除
  }
});

Fundamentally, it is correct for the package to support ESM, but legacy.inconsistentCjsInterop is provided as a temporary measure until then.

Increased browser target

Minimum supported version updated.

BrowserVite 7Vite 8
Chrome107111
Edge107111
Firefox104114
Safari16.016.4

This change is in line with Baseline Widely Available as of January 2026 and will not affect most users, but projects that require older browser support should check.

Changes for plugin authors

When converting non-JavaScript content to JavaScript using load or transform hooks, moduleType: 'js' is now required to be specified. Also, the error handling of the build() function has changed, so that it now returns an errors array wrapped in BundleError.

Context of VoidZero and Vite+

The release of Vite 8 is part of a larger movement.

Founded by Vite author Evan You (also Vue.js author), VoidZero has raised a 4.6MseedledbyAccel,followedbya4.6M seed led by Accel, followed by a 12.5M Series A. A company that brings together core developers of Vite, Vitest, Rolldown, and OXC, and is promoting the conversion of JavaScript tool chains to Rust as a business.

The day after Vite 8 was released (March 13th), VoidZero released Vite+ as open source under the MIT license. Vite+ is a single toolchain that integrates the following tools:

ToolsRole
Vite 8Development server build
Vitest 4.1Test
Oxlint 1.52Linter
Oxfmt (beta)Formatter
RolldownBundler
tsdownlibrary bundle
Vite TaskTask Runner

You can operate vp dev, vp build, vp test, and vp check using the vp CLI command. It also includes automatic management of Node.js versions and package managers.

Looking at the flow from webpack → Vite → Vite+, we can see that the front-end build toolchain is moving from a combination of individual tools such as ESLint, Prettier, Jest, and webpack to an integrated toolchain based on Rust. We are trying to achieve the direction that Rome and Biome were aiming at at the scale of Vite’s ecosystem (65 million downloads per week).

The power of Vite 8 shown by vinext

vinext (Cloudflare’s reimplementation of Next.js on Vite), which I mentioned in this blog, benefits directly from Vite 8.

In the vinext benchmark, the following results were obtained for the App Router application with the same 33 routes.

  • Vite 7 (Rollup): 4.64 seconds
  • Vite 8 (Rolldown): 1.67 seconds (2.8x speed)

The difference between Vite 7 and 8 alone is 2.8 times faster. This is 4.4 times faster than Next.js 16.1.6 (Turbopack), which takes 7.38 seconds. This is a good example of how effective unification to Rolldown is in actual production.

Relationship with Astro 6

Astro 6.0 was released three days before Vite 8 was released (March 10th). Astro 6 is based on Vite 7, with a completely rewritten development server using Vite’s Environment API. There are significant improvements on the DX side, such as being able to run code during development with the same runtime as production, and being able to access Cloudflare Workers bindings locally.

Astro 6 is Vite 7, but it is likely that the next major Astro 7 will transition to Vite 8. This will combine Vite 8’s Rolldown integration with Astro’s experimental Rust compiler (@astrojs/compiler-rs). The .astro compiler, which was made in Go, will be replaced with one made in Rust, and the bundler will also be Rolldown, made in Rust, so the entire build pipeline will be unified to Rust.

If you want to move to Astro 6 at this point, you can leave the Vite 7 settings as is. However, if you have directly customized Vite settings, Vite 8 will change the options to esbuildoxc and build.rollupOptionsbuild.rolldownOptions, so you may need to rewrite the settings when migrating to Astro 7. Whether Astro will absorb it or not depends on future release notes.