Overview
The Oxc Minifier is a high-performance JavaScript minification tool that produces the smallest possible output while maintaining correctness. It implements 17+ optimization passes inspired by industry-leading minifiers like Closure Compiler, Terser, esbuild, and SWC.
Maximum Compression Fixed-point iteration ensures all optimization opportunities are found.
100% Correct Extensively tested against Test262, Babel, and TypeScript test suites.
Dead Code Elimination Removes unreachable code and unused declarations.
Variable Mangling Renames variables to shortest possible names.
Features
Compression Techniques
Peephole Optimizations
Statement Optimization
Function Optimization
Variable & Scope
Constant folding : 1 + 2 → 3
Expression simplification : !!x → Boolean(x)
Boolean optimization : x === true → x
Comparison folding : x < y && x < z → x < Math.min(y, z)
Dead code removal : Remove unreachable code
Shorthand properties : {x: x} → {x}
If statement folding : Remove empty branches
Conditional flattening : Simplify nested conditions
Switch to if : Convert simple switches
Loop optimization : Optimize for/while loops
Return statement merging : Combine consecutive returns
Inline expansion : Inline simple functions
Function hoisting : Hoist function declarations
Arrow function conversion : Convert to arrow when beneficial
IIFE removal : Remove unnecessary IIFEs
Variable merging : Combine variable declarations
Scope hoisting : Move declarations to optimal scope
Name mangling : Shorten variable names
Unused variable removal : Remove dead assignments
Mangling Options
Identifiers : Rename local variables to a, b, c, etc.
Properties : Optionally mangle object properties
Top-level : Optionally mangle top-level names
Keep names : Preserve specific variable/function names
Private members : Mangle class private fields
Node.js API
Installation
Basic Usage
import { minify } from 'oxc-minify' ;
const code = `
function calculateTotal(items) {
let total = 0;
for (let i = 0; i < items.length; i++) {
total = total + items[i].price;
}
return total;
}
` ;
const result = minify ( code , {
compress: true ,
mangle: true
});
console . log ( result . code );
// Output: function calculateTotal(t){let l=0;for(let n=0;n<t.length;n++)l+=t[n].price;return l}
Minify Options
interface MinifyOptions {
/** Enable compression */
compress ?: boolean | CompressOptions ;
/** Enable variable mangling */
mangle ?: boolean | MangleOptions ;
/** Source map options */
sourceMap ?: boolean | SourceMapOptions ;
/** Keep original formatting (for debugging) */
keepFormat ?: boolean ;
}
interface CompressOptions {
/** Remove dead code */
deadCode ?: boolean ;
/** Fold constants */
foldConstants ?: boolean ;
/** Remove console.* statements */
dropConsole ?: boolean ;
/** Remove debugger statements */
dropDebugger ?: boolean ;
/** Target environment */
target ?: 'es5' | 'es2015' | 'es2016' | 'esnext' ;
/** Number of compression passes (default: until fixed point) */
passes ?: number ;
}
interface MangleOptions {
/** Mangle top-level names */
topLevel ?: boolean ;
/** Keep specific names */
keepNames ?: string [];
/** Mangle class private members */
keepPrivateMembers ?: boolean ;
}
Compression Only
import { minify } from 'oxc-minify' ;
const result = minify ( code , {
compress: {
deadCode: true ,
foldConstants: true ,
dropConsole: true ,
dropDebugger: true
},
mangle: false // No variable renaming
});
Mangling Only
const result = minify ( code , {
compress: false , // No compression
mangle: {
topLevel: true ,
keepNames: [ 'importantFunction' , 'API' ]
}
});
Advanced Options
const result = minify ( code , {
compress: {
target: 'es2015' ,
passes: 3 , // Run 3 compression passes
deadCode: true ,
foldConstants: true ,
dropConsole: true ,
dropDebugger: true
},
mangle: {
topLevel: false ,
keepNames: [ 'exports' , 'module' , 'require' ],
keepPrivateMembers: true
},
sourceMap: {
filename: 'output.js' ,
includeContent: true
}
});
console . log ( result . code );
console . log ( result . map ); // Source map
Rust API
Adding to Cargo.toml
[ dependencies ]
oxc_minifier = "0.37"
oxc_allocator = "0.37"
oxc_parser = "0.37"
oxc_span = "0.37"
oxc_codegen = "0.37"
Basic Usage
use oxc_allocator :: Allocator ;
use oxc_parser :: Parser ;
use oxc_span :: SourceType ;
use oxc_minifier :: { Minifier , MinifierOptions };
use oxc_codegen :: { Codegen , CodegenOptions };
fn main () {
let allocator = Allocator :: default ();
let source_text = r#"
function calculateTotal(items) {
let total = 0;
for (let i = 0; i < items.length; i++) {
total = total + items[i].price;
}
return total;
}
"# ;
let source_type = SourceType :: mjs ();
// Parse
let ret = Parser :: new ( & allocator , source_text , source_type ) . parse ();
let mut program = ret . program;
// Minify
let options = MinifierOptions :: default ();
let minifier = Minifier :: new ( options );
let ret = minifier . minify ( & allocator , & mut program );
// Generate code
let code = Codegen :: new ()
. with_options ( CodegenOptions {
minify : true ,
.. CodegenOptions :: default ()
})
. build ( & program )
. code;
println! ( "{}" , code );
}
Minifier Options
use oxc_minifier :: { MinifierOptions , CompressOptions , MangleOptions };
let options = MinifierOptions {
mangle : Some ( MangleOptions {
top_level : false ,
keep_names : vec! [ "exports" . to_string (), "require" . to_string ()],
keep_private_members : true ,
.. MangleOptions :: default ()
}),
compress : Some ( CompressOptions {
dead_code : true ,
fold_constants : true ,
drop_console : true ,
drop_debugger : true ,
target : ESTarget :: ES2015 ,
passes : None , // Until fixed point
.. CompressOptions :: default ()
}),
};
Dead Code Elimination Only
let minifier = Minifier :: new ( options );
let ret = minifier . dce ( & allocator , & mut program );
Optimization Examples
Constant Folding
const x = 1 + 2 + 3 ;
const y = 'hello' + ' ' + 'world' ;
const z = true && false ;
const a = 10 * 5 / 2 ;
Dead Code Elimination
function example () {
if ( false ) {
console . log ( 'unreachable' );
}
return 42 ;
console . log ( 'also unreachable' );
}
const unused = 123 ;
Boolean Optimization
const a = x === true ;
const b = y === false ;
const c = !! z ;
const d = Boolean ( w );
Variable Merging
function process () {
var x = 1 ;
var y = 2 ;
var z = 3 ;
return x + y + z ;
}
Property Shorthand
const obj = {
x: x ,
y: y ,
method : function () {}
};
Full Minification
Input
Output (Compressed + Mangled)
function calculateDiscount ( price , discountPercent ) {
if ( discountPercent <= 0 || discountPercent > 100 ) {
throw new Error ( 'Invalid discount' );
}
const discountAmount = price * ( discountPercent / 100 );
const finalPrice = price - discountAmount ;
return finalPrice ;
}
const result = calculateDiscount ( 100 , 20 );
console . log ( result );
Advanced Features
Tree Shaking
Remove unused exports and imports:
const result = minify ( code , {
compress: {
deadCode: true ,
treeshake: true
}
});
Multiple Passes
Run multiple compression passes for maximum compression:
const result = minify ( code , {
compress: {
passes: 5 // Run 5 passes
}
});
By default, the minifier runs until a fixed point (no further optimizations possible).
Keep Specific Names
Prevent mangling of specific identifiers:
const result = minify ( code , {
mangle: {
keepNames: [
'jQuery' ,
'$' ,
'exports' ,
'require' ,
'module'
]
}
});
Target Environment
Optimize for specific ECMAScript version:
const result = minify ( code , {
compress: {
target: 'es2015' // Use ES2015+ features
}
});
Benchmarks
The minifier is highly optimized for performance:
Tool Time (1000 files) Size Reduction Oxc Minifier ~2s ~45% Terser ~25s ~50% esbuild ~1.5s ~40%
Oxc balances speed and compression ratio. While Terser may achieve slightly better compression, Oxc is significantly faster.
Compression Statistics
Typical compression results:
JavaScript libraries : 40-50% size reduction
Application code : 35-45% size reduction
With gzip : Additional 60-70% reduction
With Brotli : Additional 70-80% reduction
Integration
Bundler Plugins
Rollup
Webpack
Vite
esbuild
import oxc from '@rollup/plugin-oxc' ;
export default {
plugins: [
oxc ({
minify: true ,
compress: {
dropConsole: true
},
mangle: {
topLevel: true
}
})
]
} ;
const OxcMinifierPlugin = require ( 'oxc-webpack-plugin' );
module . exports = {
optimization: {
minimize: true ,
minimizer: [
new OxcMinifierPlugin ({
compress: true ,
mangle: true
})
]
}
};
import { defineConfig } from 'vite' ;
import oxc from 'vite-plugin-oxc' ;
export default defineConfig ({
plugins: [
oxc ({
minify: {
compress: true ,
mangle: true
}
})
]
}) ;
const esbuild = require ( 'esbuild' );
const oxc = require ( 'esbuild-plugin-oxc' );
esbuild . build ({
entryPoints: [ 'src/index.js' ],
bundle: true ,
minify: false , // Disable esbuild minification
plugins: [
oxc ({
minify: true
})
]
});
CLI Usage (via oxc)
# Minify a single file
oxc minify input.js -o output.min.js
# Minify with options
oxc minify input.js -o output.min.js --compress --mangle
# Minify multiple files
oxc minify src/ ** / * .js --out-dir dist
# Generate source maps
oxc minify input.js -o output.min.js --source-map
Best Practices
Development vs Production Use compression only in production builds for faster development.
Source Maps Always generate source maps for production debugging.
Test After Minification Run tests on minified code to catch edge cases.
Keep Critical Names Preserve names that are accessed externally or via reflection.
Common Pitfalls
eval() usage : May break with aggressive mangling
Property access via strings : Use keepNames for dynamic properties
External APIs : Don’t mangle exported function names
Polyfills : May need to exclude certain names
Comparison with Other Minifiers
vs Terser
Feature Oxc Terser Speed Very Fast Slow Compression Good Excellent Correctness 100% 99.9% ES2024 Support Yes Partial Configuration Simple Complex
vs esbuild
Feature Oxc esbuild Speed Comparable Slightly Faster Compression Better Good Optimizations 17+ passes Fewer passes Mangling Advanced Basic
vs SWC
Feature Oxc SWC Speed Comparable Comparable Compression Better Good Integration Growing Mature Optimization More passes Fewer passes
Limitations
No HTML/CSS minification : JavaScript only
Limited property mangling : Conservative by default
No custom plugins : Built-in optimizations only
Debugging Minified Code
Source Maps
Always use source maps in production:
const result = minify ( code , {
compress: true ,
mangle: true ,
sourceMap: {
filename: 'bundle.js' ,
url: 'bundle.js.map' ,
includeContent: true
}
});
// Write source map
fs . writeFileSync ( 'bundle.js.map' , JSON . stringify ( result . map ));
For debugging, keep formatting:
const result = minify ( code , {
compress: true ,
mangle: false ,
keepFormat: true // Preserve whitespace and newlines
});
Resources
GitHub Repository Source code and examples
Rust Docs Complete Rust API documentation
npm Package Node.js bindings
Playground Try minification online
FAQ
Why doesn't minification reduce my bundle size by 50%?
Actual reduction depends on code style and patterns. Well-written modern code may see 30-40% reduction. Verbose code with many comments can see 50%+ reduction.
Is it safe to use in production?
Yes! The minifier is extensively tested against Test262, Babel, and TypeScript test suites. However, always test your specific codebase.
Can I mangle property names?
Property mangling is conservative by default to avoid breaking code. You can enable it for specific properties.
Does it work with TypeScript?
Yes, but TypeScript must be transpiled to JavaScript first using the transformer.
How many compression passes should I use?
The default (until fixed point) is recommended. Manual passes (e.g., 3-5) can be faster with similar results.
Why is my code breaking after minification?
Common causes: eval() usage, dynamic property access, or external name dependencies. Use keepNames to preserve critical identifiers.