Skip to main content

Overview

The Oxc Transformer is a high-performance code transformation engine that transpiles modern JavaScript and TypeScript to older JavaScript versions. It’s designed as a Babel alternative with significantly better performance.

TypeScript Transpilation

Strip TypeScript types and transform TS-specific syntax.

JSX/React

Transform JSX to JavaScript with React or automatic runtime.

ES2015-ES2026

Transpile modern JavaScript to ES5/ES2015 for compatibility.

Decorators & Proposals

Support for Stage 3 decorators and upcoming features.

Features

TypeScript Transformation

  • Type Stripping: Remove all TypeScript type annotations
  • Enum Transpilation: Convert TypeScript enums to JavaScript
  • Namespace Support: Handle TypeScript namespaces
  • Decorators: Stage 3 decorator support
  • Import Type Removal: Strip type-only imports
  • JSX in TSX: Handle JSX in TypeScript files

JSX Transformation

  • React Classic: Transform to React.createElement
  • React Automatic: Modern automatic JSX runtime
  • React Fast Refresh: Hot module reloading support
  • Development Mode: Add source locations and keys
  • Fragment Support: Handle <> syntax

ES2015+ Features

  • Arrow functions
  • Classes
  • Template literals
  • Destructuring
  • Spread operator
  • For-of loops
  • Block scoping

Node.js API

Installation

npm
npm install oxc-transform

Basic Usage

import { transform } from 'oxc-transform';

const result = transform('source.tsx', sourceCode, {
  typescript: true,
  jsx: {
    runtime: 'automatic'
  }
});

console.log(result.code);
console.log(result.map); // Source map

Transform Options

interface TransformOptions {
  /** TypeScript options */
  typescript?: TypeScriptOptions;
  
  /** JSX/React options */
  jsx?: JsxOptions;
  
  /** Target environment */
  env?: EnvOptions;
  
  /** ES2015+ features */
  es2015?: ES2015Options;
  es2016?: ES2016Options;
  es2017?: ES2017Options;
  // ... up to es2026
  
  /** Stage 3 decorators */
  decorator?: DecoratorOptions;
  
  /** Compiler assumptions for smaller output */
  assumptions?: CompilerAssumptions;
}

TypeScript Transformation

import { transform } from 'oxc-transform';

const tsCode = `
interface User {
  name: string;
  age: number;
}

const greet = (user: User): string => {
  return \`Hello, \${user.name}!\`;
};

enum Status {
  Active,
  Inactive
}
`;

const result = transform('example.ts', tsCode, {
  typescript: {
    // Only transform syntax, don't polyfill
    onlyRemoveTypeImports: true,
    
    // Rewrite .ts extensions to .js in imports
    rewriteImportExtensions: {
      mode: 'rewrite'
    }
  }
});

console.log(result.code);
// Output: JavaScript with types removed

JSX Transformation

import { transform } from 'oxc-transform';

const jsxCode = `
function Button({ label }) {
  return <button onClick={() => alert('Clicked!')}>{label}</button>;
}
`;

const result = transform('Button.jsx', jsxCode, {
  jsx: {
    runtime: 'automatic',  // Modern JSX runtime
    development: true,     // Add __source and __self
    importSource: 'react'  // Import from 'react/jsx-runtime'
  }
});

Target Environment

import { transform } from 'oxc-transform';

const modernCode = `
const obj = { ...spread, key: 'value' };
const arr = [1, 2, 3];
const sum = arr.reduce((a, b) => a + b, 0);
`;

// Target specific browsers
const result = transform('example.js', modernCode, {
  env: {
    targets: {
      chrome: '90',
      firefox: '88',
      safari: '14'
    }
  }
});

// Or use browserslist query
const result2 = transform('example.js', modernCode, {
  env: {
    targets: '> 0.25%, not dead'
  }
});

React Fast Refresh

const result = transform('Component.jsx', code, {
  jsx: {
    runtime: 'automatic',
    development: true,
    refresh: {
      refreshReg: '$RefreshReg$',
      refreshSig: '$RefreshSig$'
    }
  }
});

// Use with webpack or vite HMR

Rust API

Adding to Cargo.toml

Cargo.toml
[dependencies]
oxc_transformer = "0.37"
oxc_allocator = "0.37"
oxc_parser = "0.37"
oxc_span = "0.37"

Basic Usage

use oxc_allocator::Allocator;
use oxc_parser::Parser;
use oxc_span::SourceType;
use oxc_transformer::{Transformer, TransformOptions};
use oxc_semantic::SemanticBuilder;

fn main() {
    let allocator = Allocator::default();
    let source_text = r#"
        interface User {
            name: string;
        }
        const greet = (user: User) => `Hello, ${user.name}!`;
    "#;
    let source_type = SourceType::ts();
    let source_path = std::path::Path::new("example.ts");
    
    // Parse
    let ret = Parser::new(&allocator, source_text, source_type).parse();
    let mut program = ret.program;
    
    // Build semantic information
    let semantic = SemanticBuilder::new().build(&program).semantic;
    let scoping = semantic.into_scoping();
    
    // Transform
    let options = TransformOptions::default();
    let transformer = Transformer::new(&allocator, source_path, &options);
    let result = transformer.build_with_scoping(scoping, &mut program);
    
    // Generate code
    use oxc_codegen::{Codegen, CodegenOptions};
    let codegen_options = CodegenOptions::default();
    let code = Codegen::new().with_options(codegen_options).build(&program).code;
    
    println!("{}", code);
}

TypeScript Options

use oxc_transformer::{TransformOptions, TypeScriptOptions, RewriteExtensionsMode};

let options = TransformOptions {
    typescript: TypeScriptOptions {
        /// Rewrite `.ts`/`.mts`/`.cts` extensions to `.js`/`.mjs`/`.cjs`
        rewrite_import_extensions: Some(RewriteExtensionsMode::Rewrite),
        
        /// Only remove type imports, keep value imports
        only_remove_type_imports: true,
        
        ..TypeScriptOptions::default()
    },
    ..TransformOptions::default()
};

JSX Options

use oxc_transformer::{JsxOptions, JsxRuntime, ReactRefreshOptions};

let options = TransformOptions {
    jsx: JsxOptions {
        runtime: JsxRuntime::Automatic,
        development: true,
        import_source: Some("react".to_string()),
        
        /// React Fast Refresh
        refresh: Some(ReactRefreshOptions {
            refresh_reg: "$RefreshReg$".to_string(),
            refresh_sig: "$RefreshSig$".to_string(),
            emit_full_signatures: false,
        }),
        
        ..JsxOptions::default()
    },
    ..TransformOptions::default()
};

Target Environment

use oxc_transformer::{EnvOptions, EngineTargets};

let options = TransformOptions {
    env: EnvOptions {
        targets: EngineTargets {
            chrome: Some("90".to_string()),
            firefox: Some("88".to_string()),
            safari: Some("14".to_string()),
            ..EngineTargets::default()
        },
        ..EnvOptions::default()
    },
    ..TransformOptions::default()
};

Transformation Examples

TypeScript to JavaScript

interface Point {
  x: number;
  y: number;
}

class Vector implements Point {
  constructor(
    public x: number,
    public y: number
  ) {}
  
  magnitude(): number {
    return Math.sqrt(this.x ** 2 + this.y ** 2);
  }
}

const v: Vector = new Vector(3, 4);
console.log(v.magnitude());

JSX to JavaScript

function TodoList({ items }) {
  return (
    <ul className="todo-list">
      {items.map(item => (
        <li key={item.id}>
          <span>{item.text}</span>
        </li>
      ))}
    </ul>
  );
}

Modern JavaScript to ES5

const data = {
  user: {
    name: 'John',
    age: 30
  }
};

const userName = data?.user?.name ?? 'Anonymous';

const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2);

class Counter {
  #count = 0;
  
  increment() {
    this.#count++;
  }
  
  get value() {
    return this.#count;
  }
}

Advanced Features

Compiler Assumptions

Optimize output with compiler assumptions:
const result = transform('example.js', code, {
  assumptions: {
    noDocumentAll: true,
    noClassCalls: true,
    noNewArrows: true,
    pureGetters: true,
    setPublicClassFields: true
  }
});

Helper Functions

Control how helpers are imported:
const result = transform('example.js', code, {
  helper: {
    mode: 'external',  // or 'inline'
    importSource: '@babel/runtime'
  }
});

Decorator Support

const decoratorCode = `
@sealed
class Example {
  @logged
  method() {}
}
`;

const result = transform('example.ts', decoratorCode, {
  decorator: {
    version: '2023-05'  // Stage 3 decorators
  }
});

Framework Integrations

Vite Plugin

vite.config.ts
import { defineConfig } from 'vite';
import oxc from 'vite-plugin-oxc';

export default defineConfig({
  plugins: [
    oxc({
      typescript: true,
      jsx: {
        runtime: 'automatic'
      }
    })
  ]
});

Rollup Plugin

rollup.config.js
import oxc from '@rollup/plugin-oxc';

export default {
  plugins: [
    oxc({
      include: ['**/*.ts', '**/*.tsx'],
      typescript: {
        declaration: true
      }
    })
  ]
};

Webpack Loader

webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.(js|jsx|ts|tsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'oxc-loader',
          options: {
            typescript: true,
            jsx: {
              runtime: 'automatic'
            }
          }
        }
      }
    ]
  }
};

Performance

Benchmarks

The transformer is significantly faster than Babel:
ToolTime (1000 files)
Oxc Transform~1s
SWC~2s
Babel~15s

Performance Tips

Disable Unnecessary Features

Only enable transformations you need for your target environment.

Use Assumptions

Compiler assumptions reduce output size and improve performance.

Parallel Processing

Transform files in parallel for maximum throughput.

Cache Results

Cache transformation results when possible.

Migration from Babel

Configuration Comparison

{
  "presets": [
    ["@babel/preset-env", {
      "targets": "> 0.25%, not dead"
    }],
    "@babel/preset-typescript",
    ["@babel/preset-react", {
      "runtime": "automatic"
    }]
  ]
}

Plugin Equivalents

Babel PluginOxc Option
@babel/preset-envenv: { targets }
@babel/preset-typescripttypescript: true
@babel/preset-reactjsx: { runtime }
@babel/plugin-transform-runtimehelper: { mode }
@babel/plugin-proposal-decoratorsdecorator: {}

Limitations

  • No Babel plugin API: Can’t use Babel plugins
  • Limited customization: Some advanced Babel features not available
  • Breaking changes: API may change in major versions

Resources

GitHub Repository

Source code and examples

Rust Docs

Complete Rust API documentation

npm Package

Node.js bindings

Playground

Try transformations online

FAQ

No, Oxc doesn’t support Babel’s plugin API. However, most common transformations are built-in.
The output is functionally equivalent but may differ in formatting and variable naming. The transformer aims for correctness, not byte-for-byte compatibility.
Yes, Stage 3 decorators with metadata are supported.
Not directly, but you can eject and configure webpack to use oxc-loader.
Yes, source maps are generated automatically and included in the output.

Build docs developers (and LLMs) love