Vite 22 ⚡ Oxc — The high-performance parser & transformer
Oxc is not a single tool. It is a collection of Rust-based compiler components—a parser, a transformer, a minifier, and a resolver—that share the same foundation and are designed to work together . In the Vite 8 toolchain, Oxc sits underneath Rolldown. It parses the JavaScript and TypeScript, transforms the JSX and TypeScript syntax, resolves the module imports, and minifies the output. Rolldown orchestrates the bundle; Oxc does the language-level work . The distinction matters because the migration from esbuild to Oxc is not a single setting. It touches the transform pipeline, the minification behavior, the module resolution, and the TypeScript emit semantics.
The performance numbers are the reason for the swap. Oxc’s parser is roughly 3× faster than SWC and 5× faster than Biome, parsing TypeScript’s own typescript.js in about 26ms where SWC takes 84ms and Biome takes 130ms . The transformer is 4× faster than SWC and 40× faster than Babel, while using less memory and shipping a smaller package . These gains compound across the build because the parser and transformer are invoked for every module in the graph. A faster parser is a faster dev server startup, a faster production build, and a faster lint pass when the same foundation powers Oxlint .
Key point: Oxc replaces esbuild as the transform and minification layer in Vite 8. The configuration surface is the oxc option (renamed from esbuild) for transforms, and build.rolldownOptions.output.minify for minifier options. The old build.minify: 'oxc' shorthand enables the minifier with defaults but does not expose the compression options—the full configuration goes through Rolldown’s output options.
Why Oxc replaces esbuild in the toolchain
The unified foundation problem. Before Vite 8, the toolchain used esbuild for development transforms and Rollup for production bundling. Each tool had its own parser, its own resolver, and its own assumptions about JavaScript syntax. A change in one pipeline could produce a different result in the other, and the glue code that kept them aligned was a maintenance burden . Oxc is the single foundation that both Rolldown and the development pipeline share. The parser that Rolldown uses for bundling is the same parser that transforms the TypeScript, and the same parser that Oxlint uses for linting . The consistency is not a configuration option; it is the architecture.
The TypeScript and JSX transform. Oxc’s transformer handles TypeScript syntax stripping, JSX transformation, and syntax lowering to ES2015 . It is designed to match esbuild’s behavior for the common cases, but it makes different assumptions in a few edge cases. The most consequential is the TypeScript enum handling. esbuild inlines numeric enum values and preserves string enum patterns. Oxc aligns more closely with TypeScript’s own emit behavior, which means it does not inline const enum declarations across file boundaries when isolatedModules is enabled . Vite sets isolatedModules: true implicitly because it transforms files individually, so a project that relies on cross-file const enum inlining must switch to a regular enum or a plain object with as const.
The minifier’s different assumptions. Oxc’s minifier is not a drop-in replacement for esbuild’s minifier. The two tools make slightly different assumptions about source code, and the Vite migration guide links to a comparison of those assumptions . The property mangling options that esbuild supported (mangleProps, reserveProps, mangleQuoted, mangleCache) are not supported by Oxc . A project that relied on property mangling must either accept the larger output or report the gap to the Oxc team. The minifier’s compression options are configured through Rolldown’s output options, not through a top-level Vite key. The dropConsole option, for example, is set at build.rolldownOptions.output.minify.compress.drop_console—and the casing matters. The Oxc API uses snake_case, so dropConsole silently does nothing where drop_console works .
The trade-off. Oxc is faster and more consistent, but it is not a perfect drop-in for every esbuild behavior. The migration is a rename for the common case, and a behavioral adjustment for the edge cases. A project that uses standard TypeScript, standard JSX, and standard minification will not notice the difference except in the build time. A project that uses const enum, property mangling, or esbuild-specific transform options must audit those specific features .
a. Configuring the Oxc transformer
The oxc option replaces the esbuild option in vite.config.ts. The old name is auto-converted with a deprecation warning, but the new name is the one that will remain . The transform options cover JSX, TypeScript, and the target syntax level.
// vite.config.ts — the oxc transform configuration
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
// The oxc option replaces the esbuild option.
// It configures the transform pipeline that runs before bundling.
oxc: {
jsx: {
// The automatic runtime uses the jsx() function from react/jsx-runtime.
// The classic runtime uses React.createElement.
runtime: 'automatic',
// The import source is the package that provides the JSX runtime.
importSource: 'react',
},
// The target syntax level. Oxc lowers the syntax to this level.
// The default is the browser target from the build configuration.
target: 'es2020',
},
});
The oxc option is the replacement for esbuild, but the mapping is not one-to-one for every sub-option. The jsxFactory and jsxFragment options from esbuild map to oxc.jsx.pragma and oxc.jsx.pragmaFrag. The jsx: 'transform' string maps to oxc.jsx: { runtime: 'classic' }, and jsx: 'automatic' maps to oxc.jsx: { runtime: 'automatic' } . The banner and footer options from esbuild have no direct equivalent in Oxc; a custom plugin with a transform hook is the replacement .
The TypeScript configuration must match the Oxc configuration. If the project uses the automatic JSX runtime, tsconfig.json must have "jsx": "react-jsx" and "jsxImportSource": "react". If the project uses the classic runtime, the tsconfig.json must have "jsx": "react" and the jsxFactory option. A mismatch between the two files is the most common cause of JSX-related build failures after migration . The Oxc transform does not read tsconfig.json directly for the JSX runtime; it uses the oxc.jsx configuration. The two must be kept in sync manually.
b. Configuring the Oxc minifier
The minifier configuration is not on the oxc option. It is on the Rolldown output options. The build.minify: 'oxc' shorthand enables the minifier with defaults, but the compression options are only available through build.rolldownOptions.output.minify .
// vite.config.ts — the oxc minifier configuration
import { defineConfig } from 'vite';
export default defineConfig({
build: {
// The minify shorthand enables the minifier with defaults.
// But it does not expose the compression options.
minify: 'oxc',
rolldownOptions: {
output: {
// The full minifier configuration goes here.
// This object is passed to the Oxc minifier inside Rolldown.
minify: {
compress: {
// The drop_console option removes console.* calls.
// The casing is snake_case. dropConsole (camelCase)
// silently does nothing.
drop_console: true,
// Other compression options are passed here.
},
},
},
},
},
});
The double configuration is a source of confusion. Setting build.minify: 'oxc' and build.rolldownOptions.output.minify.compress.drop_console: true at the same time is not necessary. The rolldownOptions route alone engages the Oxc minifier and passes the options. The build.minify: 'oxc' route enables the minifier but does not plumb the compression options through . The canonical configuration is the rolldownOptions route, without the shorthand. If the shorthand is used for clarity, the compression options are still only effective through the rolldownOptions object.
The snake_case casing is a specific trap. The Oxc API uses drop_console, not dropConsole. The camelCase version is silently ignored, which means the console calls remain in the output with no error and no warning . The same applies to other compression options: the Oxc API names are the ones that work, and they are documented in the Rolldown CompressOptions type.
Complete Example Session
// ============================================
// PART 1: THE RENAMED TRANSFORM OPTION
// ============================================
// vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
// The esbuild option is renamed to oxc.
// The old name is auto-converted but deprecated.
oxc: {
jsx: {
runtime: 'automatic',
importSource: 'react',
},
},
});
// ============================================
// PART 2: THE JSX RUNTIME MAPPING
// ============================================
// esbuild configuration (before):
// esbuild: {
// jsx: 'automatic',
// jsxImportSource: 'react',
// }
// oxc configuration (after):
// oxc: {
// jsx: {
// runtime: 'automatic',
// importSource: 'react',
// },
// }
// The mapping is not one-to-one for every option.
// The jsxFactory option maps to oxc.jsx.pragma.
// The jsxFragment option maps to oxc.jsx.pragmaFrag.
// ============================================
// PART 3: THE TSCONFIG SYNC
// ============================================
// tsconfig.json
// {
// "compilerOptions": {
// "jsx": "react-jsx",
// "jsxImportSource": "react"
// }
// }
// The tsconfig must match the oxc configuration.
// A mismatch causes build failures that are hard to trace.
// ============================================
// PART 4: THE MINIFIER SHORTHAND
// ============================================
// vite.config.ts — the shorthand
export default defineConfig({
build: {
// The shorthand enables the Oxc minifier with defaults.
// It does not expose the compression options.
minify: 'oxc',
},
});
// ============================================
// PART 5: THE MINIFIER OPTIONS
// ============================================
// vite.config.ts — the full configuration
export default defineConfig({
build: {
rolldownOptions: {
output: {
minify: {
compress: {
// The snake_case option name is the one that works.
drop_console: true,
},
},
},
},
},
});
// The shorthand is not needed when the rolldownOptions route is used.
// The rolldownOptions route engages the Oxc minifier and passes the options.
// ============================================
// PART 6: THE CONST ENUM EDGE CASE
// ============================================
// tsconfig.json — with isolatedModules
// {
// "compilerOptions": {
// "isolatedModules": true
// }
// }
// Oxc does not inline const enum across file boundaries
// when isolatedModules is enabled.
// The fix is to use a regular enum or a plain object.
// ❌ const enum Status { Active = 1, Inactive = 0 }
// ✅ enum Status { Active = 1, Inactive = 0 }
// ✅ const Status = { Active: 1, Inactive: 0 } as const;
// ============================================
// PART 7: THE PROPERTY MANGLING GAP
// ============================================
// esbuild supported property mangling:
// esbuild: {
// mangleProps: /^_/,
// reserveProps: /^__/,
// }
// Oxc does not support property mangling.
// The options are not available.
// The output is larger if the project relied on them.
// ============================================
// PART 8: THE DECORATOR WORKAROUND
// ============================================
// Oxc does not yet support native decorator lowering.
// The workaround is to use a Babel or SWC plugin.
// vite.config.ts
import { defineConfig } from 'vite';
import babel from '@rolldown/plugin-babel';
export default defineConfig({
plugins: [
babel({
// The Babel plugin handles the decorator transform.
// Oxc handles the rest.
}),
],
});
// ============================================
// PART 9: THE PERFORMANCE VERIFICATION
// ============================================
// The Oxc parser is 3x faster than SWC.
// The Oxc transformer is 4x faster than SWC and 40x faster than Babel.
// The Oxc minifier is the default in Vite 8.
// The build time should be lower than the esbuild-based build.
//
// The dev server startup is faster because the parser is faster.
// The production build is faster because the transformer and minifier are faster.
// ============================================
// PART 10: THE VERIFICATION CHECKLIST
// ============================================
// [ ] The esbuild option is renamed to oxc.
// [ ] The tsconfig JSX settings match the oxc.jsx settings.
// [ ] The minifier options are on rolldownOptions.output.minify.
// [ ] The snake_case casing is used for drop_console.
// [ ] The const enum usage is audited if isolatedModules is enabled.
// [ ] The property mangling options are audited if they were used.
// [ ] The decorator transform is handled by a plugin if needed.
The ten parts covered the renamed transform option, the JSX runtime mapping, the tsconfig sync, the minifier shorthand, the minifier options, the const enum edge case, the property mangling gap, the decorator workaround, the performance verification, and the checklist. The through-line is that the Oxc migration is a rename for the common case and a behavioral audit for the edge cases.
Quick Reference
The option renames
| esbuild | oxc |
|---|---|
esbuild | oxc |
esbuild.jsxFactory | oxc.jsx.pragma |
esbuild.jsxFragment | oxc.jsx.pragmaFrag |
esbuild.jsx: 'automatic' | oxc.jsx: { runtime: 'automatic' } |
esbuild.jsx: 'transform' | oxc.jsx: { runtime: 'classic' } |
The minifier configuration
| Setting | Location | Casing |
|---|---|---|
| Enable minifier | build.minify: 'oxc' | — |
| Compression options | build.rolldownOptions.output.minify.compress | snake_case |
| Drop console | compress.drop_console | snake_case |
The performance gains
| Tool | Comparison | Source |
|---|---|---|
| Parser | 3× faster than SWC | |
| Transformer | 4× faster than SWC, 40× faster than Babel | |
| Minifier | Default in Vite 8 |
The edge cases
| Edge case | Behavior | Fix |
|---|---|---|
const enum with isolatedModules | Not inlined across files | Use regular enum or as const object |
| Property mangling | Not supported | Accept larger output or report the gap |
| Decorators | Not yet supported natively | Use @rolldown/plugin-babel or @rollup/plugin-swc |
jsxFactory mismatch | Build failure | Sync tsconfig.json and oxc.jsx |
Best Practices
✅ Do This:
// Use the oxc option for transforms
oxc: { jsx: { runtime: 'automatic', importSource: 'react' } } // ✅
// Use rolldownOptions for minifier options
rolldownOptions: { output: { minify: { compress: { drop_console: true } } } } // ✅
// Sync tsconfig and oxc.jsx
// "jsx": "react-jsx", "jsxImportSource": "react" // ✅
// Use snake_case for Oxc minifier options
compress: { drop_console: true } // ✅
❌ Don’t Do This:
// Use camelCase for Oxc minifier options
compress: { dropConsole: true } // silently does nothing // ❌
// Rely on const enum across files
const enum Status { Active = 1 } // not inlined // ❌
// Use property mangling
mangleProps: /^_/ // not supported // ❌
// Assume the jsxFactory mapping is automatic
// The tsconfig and oxc.jsx must both be updated // ❌
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
drop_console has no effect | dropConsole (camelCase) was used | Use drop_console (snake_case) |
| JSX build fails | tsconfig.json and oxc.jsx disagree | Sync the runtime and import source |
const enum breaks | isolatedModules is enabled | Use regular enum or as const object |
| Decorators break | Oxc does not support decorator lowering | Use a Babel or SWC plugin |
| Property mangling ignored | Oxc does not support it | Accept the output size or report the gap |
Real-World Examples
1. Rename esbuild to oxc
oxc: { jsx: { runtime: 'automatic' } }
2. Minifier shorthand
build: { minify: 'oxc' }
3. Minifier options
build: { rolldownOptions: { output: { minify: { compress: { drop_console: true } } } } }
4. tsconfig sync
{ "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "react" } }
5. const enum fix
const Status = { Active: 1, Inactive: 0 } as const;
6. Decorator workaround
plugins: [babel({ /* decorator transform */ })]
7. Property mangling gap
// No equivalent; output is larger
8. Performance measurement
time npm run build
9. JSX classic runtime
oxc: { jsx: { runtime: 'classic', pragma: 'h', pragmaFrag: 'Fragment' } }
10. Verification
npm run build # no JSX errors, no minifier errors
Visual
The Toolchain
┌──────────────────────────────────────────────────────────────┐
│ VITE 8 TOOLCHAIN │
│ │
│ Vite (orchestration) │
│ │ │
│ ▼ │
│ Rolldown (bundling) │
│ │ │
│ ├──▶ Oxc Parser │
│ ├──▶ Oxc Transformer │
│ ├──▶ Oxc Resolver │
│ └──▶ Oxc Minifier │
│ │
│ All five layers are maintained by VoidZero. │
│ The parser and transformer are shared with Oxlint. │
└──────────────────────────────────────────────────────────────┘
The Transform Configuration
┌──────────────────────────────────────────────────────────────┐
│ esbuild → oxc MAPPING │
│ │
│ esbuild oxc │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ jsxFactory │────▶│ jsx.pragma │ │
│ │ jsxFragment │────▶│ jsx.pragmaFrag │ │
│ │ jsx: 'automatic' │────▶│ jsx: { runtime: │ │
│ │ │ │ 'automatic' } │ │
│ │ jsx: 'transform' │────▶│ jsx: { runtime: │ │
│ │ │ │ 'classic' } │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
│ The jsxImportSource option maps to jsx.importSource. │
│ The banner/footer options have no equivalent. │
└──────────────────────────────────────────────────────────────┘
The Minifier Configuration
┌──────────────────────────────────────────────────────────────┐
│ TWO ENTRY POINTS, ONE MINIFIER │
│ │
│ build.minify: 'oxc' │
│ ┌─────────────────────┐ │
│ │ Enables the minifier│ │
│ │ with defaults │ │
│ │ No compress options │ │
│ └─────────────────────┘ │
│ │
│ build.rolldownOptions.output.minify │
│ ┌─────────────────────┐ │
│ │ Full configuration │ │
│ │ compress: { │ │
│ │ drop_console: true│ │
│ │ } │ │
│ └─────────────────────┘ │
│ │
│ The rolldownOptions route is the full configuration. │
│ The shorthand is not needed when the full route is used. │
└──────────────────────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
| Oxc | Rust-based parser, transformer, minifier, resolver |
| Replaces | esbuild (transform and minify) |
| Transform option | oxc (was esbuild) |
| Minifier option | build.rolldownOptions.output.minify |
| Minifier casing | snake_case (drop_console) |
| Parser speed | 3× faster than SWC |
| Transformer speed | 4× faster than SWC, 40× faster than Babel |
const enum behavior | Not inlined across files with isolatedModules |
| Property mangling | Not supported |
| Decorators | Not yet supported natively |
Key takeaways:
- Oxc is the language layer beneath Rolldown. It parses, transforms, resolves, and minifies. The parser and transformer are shared with Oxlint, which is why the same foundation powers the build and the lint pass . The configuration surface is the
oxcoption for transforms androlldownOptions.output.minifyfor minifier options. - The transform option is a rename with edge cases.
esbuildbecomesoxc,jsxFactorybecomesjsx.pragma, and the JSX runtime is configured throughoxc.jsx.runtime. Thetsconfig.jsonmust match theoxc.jsxconfiguration, or the build fails . - The minifier options are on Rolldown, not on the
oxcoption. Thebuild.minify: 'oxc'shorthand enables the minifier but does not expose the compression options. The full configuration isbuild.rolldownOptions.output.minify, and the option names are snake_case . - The edge cases are specific and documented.
const enumis not inlined across files whenisolatedModulesis enabled. Property mangling is not supported. Decorators require a Babel or SWC plugin. A project that uses these features must audit them . - The performance gains are the reason for the swap. The parser is 3× faster than SWC, and the transformer is 40× faster than Babel. The gains compound across the build because every module goes through the parser and transformer .
Remember: Oxc is the compiler foundation that Vite 8 runs on. It replaces esbuild for transforms and minification, and it shares its parser and transformer with Rolldown and Oxlint. The migration is a rename for the common case and a behavioral audit for the edge cases. The transform options go on oxc, the minifier options go on rolldownOptions.output.minify, and the casing matters. The const enum and property mangling gaps are real; a project that uses them must adjust. The performance is the payoff, and it is the reason the swap happened.
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!