Skip to main content
Oxc’s minifier provides high-performance code minification with comprehensive optimization passes focused on achieving maximum compression while maintaining correctness.

Features

  • Maximum compression through fixed-point iteration
  • 17+ transformation passes and growing
  • Variable name mangling
  • Dead code elimination (DCE)
  • Peephole optimizations
  • Tree shaking
  • 100% correctness with extensive testing

Installation

Add to your Cargo.toml:
[dependencies]
oxc_minifier = "0.116.0"
oxc_parser = "0.116.0"
oxc_codegen = "0.116.0"
oxc_allocator = "0.116.0"
oxc_span = "0.116.0"

Basic Usage

use oxc_allocator::Allocator;
use oxc_codegen::{Codegen, CodegenOptions};
use oxc_minifier::{Minifier, MinifierOptions};
use oxc_parser::Parser;
use oxc_span::SourceType;

let allocator = Allocator::default();
let source = "const x = 1 + 1; console.log(x);";
let source_type = SourceType::mjs();

// Parse
let ret = Parser::new(&allocator, source, source_type).parse();
let mut program = ret.program;

// Minify
let options = MinifierOptions::default();
let ret = Minifier::new(options).minify(&allocator, &mut program);

// Generate minified code
let minified = Codegen::new()
    .with_options(CodegenOptions::minify())
    .with_scoping(ret.scoping)
    .build(&program)
    .code;

println!("{}", minified);  // const x=2;console.log(x);

Core Types

Minifier

Minifier
struct
Main minification engine.
Constructor:
impl Minifier {
    pub fn new(options: MinifierOptions) -> Self;
}
Methods:
impl Minifier {
    // Full minification (compress + mangle)
    pub fn minify(
        self,
        allocator: &'a Allocator,
        program: &mut Program<'a>
    ) -> MinifierReturn;
    
    // Dead code elimination only
    pub fn dce(
        self,
        allocator: &'a Allocator,
        program: &mut Program<'a>
    ) -> MinifierReturn;
}

MinifierOptions

MinifierOptions
struct
Configuration for minification.
pub struct MinifierOptions {
    pub mangle: Option<MangleOptions>,
    pub compress: Option<CompressOptions>,
}
mangle
Option<MangleOptions>
Variable name mangling configuration. Set to None to disable mangling.
compress
Option<CompressOptions>
Code compression configuration. Set to None to disable compression.
Defaults:
impl Default for MinifierOptions {
    fn default() -> Self {
        Self {
            mangle: Some(MangleOptions::default()),
            compress: Some(CompressOptions::default()),
        }
    }
}

MinifierReturn

MinifierReturn
struct
Result of minification.
pub struct MinifierReturn {
    pub scoping: Option<Scoping>,
    pub class_private_mappings: Option<IndexVec<ClassId, FxHashMap<String, CompactStr>>>,
    pub iterations: u8,
}
scoping
Option<Scoping>
Updated semantic scoping after minification. Pass to codegen for correct output.
class_private_mappings
Option<...>
Mappings of mangled private class member names.
iterations
u8
Number of compression iterations performed. Useful for debugging performance.

Compression Options

CompressOptions

use oxc_minifier::CompressOptions;

let compress = CompressOptions {
    max_iterations: Some(10),
    treeshake: true,
    ..CompressOptions::default()
};
max_iterations
Option<u8>
Maximum compression passes. More iterations = smaller output but slower. Default: continue until no changes.
treeshake
bool
default:"true"
Enable tree-shaking to remove unused code.
Presets:
impl CompressOptions {
    // Default balanced settings
    pub fn default() -> Self;
    
    // Maximum compression (slower)
    pub fn smallest() -> Self;
    
    // Dead code elimination only
    pub fn dce() -> Self;
}

Mangling Options

MangleOptions

use oxc_minifier::MangleOptions;

let mangle = MangleOptions {
    top_level: true,
    keep_names: MangleOptionsKeepNames::default(),
    ..Default::default()
};
top_level
bool
default:"false"
Mangle top-level variable names. Enable for modules, disable for scripts.
keep_names
MangleOptionsKeepNames
Configure which names to preserve from mangling.

MangleOptionsKeepNames

use oxc_minifier::MangleOptionsKeepNames;

let keep_names = MangleOptionsKeepNames {
    keep_class_names: vec!["MyClass".to_string()],
    keep_fn_names: vec!["myFunction".to_string()],
};

Examples

Basic Minification

use oxc_allocator::Allocator;
use oxc_codegen::{Codegen, CodegenOptions};
use oxc_minifier::{Minifier, MinifierOptions};
use oxc_parser::Parser;
use oxc_span::SourceType;

fn minify_code(source: &str) -> String {
    let allocator = Allocator::default();
    let source_type = SourceType::default();
    
    let ret = Parser::new(&allocator, source, source_type).parse();
    let mut program = ret.program;
    
    let options = MinifierOptions::default();
    let ret = Minifier::new(options).minify(&allocator, &mut program);
    
    Codegen::new()
        .with_options(CodegenOptions::minify())
        .with_scoping(ret.scoping)
        .build(&program)
        .code
}

let code = "const x = 1 + 2; console.log(x);";
let minified = minify_code(code);
assert_eq!(minified, "console.log(3);\n");

Compression Only (No Mangling)

let options = MinifierOptions {
    mangle: None,  // Disable mangling
    compress: Some(CompressOptions::default()),
};

let ret = Minifier::new(options).minify(&allocator, &mut program);

Mangling Only (No Compression)

let options = MinifierOptions {
    mangle: Some(MangleOptions::default()),
    compress: None,  // Disable compression
};

let ret = Minifier::new(options).minify(&allocator, &mut program);

Dead Code Elimination

let options = MinifierOptions {
    mangle: None,
    compress: Some(CompressOptions::dce()),
};

let ret = Minifier::new(options).dce(&allocator, &mut program);

// Or use the convenience method:
let ret = Minifier::new(options).dce(&allocator, &mut program);

Maximum Compression

let options = MinifierOptions {
    mangle: Some(MangleOptions {
        top_level: true,
        ..Default::default()
    }),
    compress: Some(CompressOptions::smallest()),
};

let ret = Minifier::new(options).minify(&allocator, &mut program);

With Source Maps

use oxc_codegen::{Codegen, CodegenOptions};
use std::path::PathBuf;

let ret = Minifier::new(options).minify(&allocator, &mut program);

let codegen_options = CodegenOptions {
    minify: true,
    source_map_path: Some(PathBuf::from("output.js.map")),
    ..Default::default()
};

let output = Codegen::new()
    .with_options(codegen_options)
    .with_scoping(ret.scoping)
    .build(&program);

std::fs::write("output.js", output.code)?;
if let Some(map) = output.map {
    std::fs::write("output.js.map", map.to_json_string())?;
}

Preserve Specific Names

use oxc_minifier::{MangleOptions, MangleOptionsKeepNames};

let mangle = MangleOptions {
    keep_names: MangleOptionsKeepNames {
        keep_class_names: vec!["Component".to_string()],
        keep_fn_names: vec!["main".to_string()],
    },
    ..Default::default()
};

let options = MinifierOptions {
    mangle: Some(mangle),
    compress: Some(CompressOptions::default()),
};

Limiting Iterations

let compress = CompressOptions {
    max_iterations: Some(5),  // Stop after 5 passes
    ..CompressOptions::default()
};

let options = MinifierOptions {
    mangle: Some(MangleOptions::default()),
    compress: Some(compress),
};

let ret = Minifier::new(options).minify(&allocator, &mut program);
println!("Completed in {} iterations", ret.iterations);

Idempotency Testing

fn test_idempotency(source: &str) {
    let mut allocator = Allocator::default();
    let options = MinifierOptions::default();
    
    // First pass
    let parsed = Parser::new(&allocator, source, SourceType::default()).parse();
    let mut program = parsed.program;
    let ret1 = Minifier::new(options.clone()).minify(&allocator, &mut program);
    let output1 = Codegen::new()
        .with_options(CodegenOptions::minify())
        .with_scoping(ret1.scoping)
        .build(&program)
        .code;
    
    // Second pass
    allocator.reset();
    let parsed = Parser::new(&allocator, &output1, SourceType::default()).parse();
    let mut program = parsed.program;
    let ret2 = Minifier::new(options).minify(&allocator, &mut program);
    let output2 = Codegen::new()
        .with_options(CodegenOptions::minify())
        .with_scoping(ret2.scoping)
        .build(&program)
        .code;
    
    assert_eq!(output1, output2, "Output should be idempotent");
}

Optimization Passes

The minifier applies numerous optimization techniques:
  • Constant folding: 1 + 23
  • Dead code elimination: Remove unreachable code
  • Expression simplification: !!xx for booleans
  • Conditional collapsing: if (true) x;x;
  • Boolean optimization: x === truex
  • Sequence optimization: Combine expressions
  • Template literal folding: `hello ${x}`"hello " + x
  • Property access optimization: x["prop"]x.prop
  • Function inlining: Inline simple functions
  • Variable merging: Combine declarations
  • **And many more…

Performance

The minifier uses several techniques for speed:
  • Fixed-point iteration: Repeats passes until no changes
  • Efficient data structures: Compact AST representation
  • In-place modification: No unnecessary allocations
  • Parallel opportunities: Independent optimizations can run concurrently

Safety and Correctness

The minifier is extensively tested:
  • Test262: ECMAScript conformance suite
  • Babel tests: Parser and transformation tests
  • TypeScript tests: Type system edge cases
  • Idempotency checks: Output should be stable
  • Snapshot tests: Regression prevention

API Documentation

For complete API documentation, see docs.rs/oxc_minifier.

Build docs developers (and LLMs) love