oxc-transform
A high-performance JavaScript and TypeScript transformer for Node.js. Transform modern JavaScript to target specific ECMAScript versions, transpile TypeScript, transform JSX, and apply code transformations.
Installation
npm install oxc-transform
Quick Start
import { transformSync } from 'oxc-transform' ;
const result = transformSync (
'app.tsx' ,
'const App = () => <div>Hello</div>;' ,
{ jsx: { runtime: 'automatic' } }
);
console . log ( result . code );
// Output: import { jsx } from "react/jsx-runtime";
// const App = () => jsx("div", { children: "Hello" });
const { transformSync } = require ( 'oxc-transform' );
const result = transformSync (
'app.jsx' ,
'const App = () => <div>Hello</div>;' ,
{ jsx: { runtime: 'automatic' } }
);
console . log ( result . code );
API Functions
Synchronous transformation on the current thread. This is the recommended function for most use cases.
function transformSync (
filename : string ,
sourceText : string ,
options ?: TransformOptions
) : TransformResult
The name of the file being transformed. Used to infer language from extension and for source maps. If using a relative path, consider setting the cwd option.
The JavaScript or TypeScript source code to transform.
Returns: TransformResult
Example
import { transformSync } from 'oxc-transform' ;
const result = transformSync (
'module.ts' ,
`
interface User {
name: string;
}
export const greet = (user: User) => \` Hello, \$ {user.name} \` ;
` ,
{
target: 'es2015' ,
sourcemap: true
}
);
console . log ( result . code );
console . log ( result . map );
Asynchronous transformation on a separate thread.
This function can be slower than transformSync due to thread spawning overhead. Use transformSync unless you have a specific need for async.
function transform (
filename : string ,
sourceText : string ,
options ?: TransformOptions
) : Promise < TransformResult >
The name of the file being transformed.
The source code to transform.
Configuration options for transformation.
Returns: Promise<TransformResult>
Comprehensive configuration options for code transformation.
Basic Options
lang
'js' | 'jsx' | 'ts' | 'tsx' | 'dts'
Explicitly specify the language. If not provided, inferred from filename.
sourceType
'script' | 'module' | 'commonjs' | 'unambiguous'
How to interpret the source code.
Current working directory. Used to resolve relative paths in other options.
Enable source map generation. Populates the map field in the result. const result = transformSync ( 'app.js' , code , { sourcemap: true });
console . log ( result . map ); // Source map object
Target Environment
target
string | string[]
default: "esnext"
Sets the target environment for the generated code. The lowest target is es2015. Single target: Multiple targets: {
target : [
'es2020' ,
'chrome58' ,
'edge16' ,
'firefox57' ,
'node12' ,
'safari11'
]
}
When set to 'esnext' (default), no transformations are applied.
TypeScript Options
Configure TypeScript-specific transformations. interface TypeScriptOptions {
// Generate .d.ts declaration files
declaration ?: IsolatedDeclarationsOptions ;
// Remove class fields without initializers
removeClassFieldsWithoutInitializer ?: boolean ;
// Rewrite import extensions (.ts -> .js)
rewriteImportExtensions ?: 'rewrite' | 'remove' | boolean ;
// Only remove type imports (preserve value imports)
onlyRemoveTypeImports ?: boolean ;
// JSX pragma for classic JSX (deprecated, use jsx option)
jsxPragma ?: string ;
jsxPragmaFrag ?: string ;
}
Declaration generation: const result = transformSync ( 'lib.ts' , code , {
typescript: {
declaration: {
stripInternal: true // Remove @internal from declarations
}
}
});
console . log ( result . declaration ); // .d.ts content
console . log ( result . declarationMap ); // declaration source map
Import extension rewriting: // Input: import { foo } from './bar.ts';
// With rewriteImportExtensions: 'rewrite'
// Output: import { foo } from './bar.js';
// With rewriteImportExtensions: 'remove'
// Output: import { foo } from './bar';
JSX/TSX Options
Configure JSX transformation. Set to 'preserve' to keep JSX syntax unchanged. interface JsxOptions {
// JSX runtime mode
runtime ?: 'classic' | 'automatic' ; // default: 'automatic'
// Development mode (adds __source, __self)
development ?: boolean ; // default: false
// Import source for JSX functions
importSource ?: string ; // default: 'react'
// Throw on XML namespaced tags
throwIfNamespace ?: boolean ; // default: true
// Mark JSX as pure for tree shaking
pure ?: boolean ; // default: true
// Classic mode options
pragma ?: string ; // default: 'React.createElement'
pragmaFrag ?: string ; // default: 'React.Fragment'
// React Fast Refresh
refresh ?: boolean | ReactRefreshOptions ;
}
Automatic runtime (React 17+): const result = transformSync ( 'App.jsx' , code , {
jsx: {
runtime: 'automatic' ,
importSource: 'react' // or 'preact', '@emotion/react', etc.
}
});
Classic runtime: const result = transformSync ( 'App.jsx' , code , {
jsx: {
runtime: 'classic' ,
pragma: 'h' , // Use h() instead of React.createElement()
pragmaFrag: 'Fragment'
}
});
React Fast Refresh: const result = transformSync ( 'App.jsx' , code , {
jsx: {
refresh: {
refreshReg: '$RefreshReg$' ,
refreshSig: '$RefreshSig$'
}
}
});
Compiler Assumptions
Set assumptions to produce smaller output. Use with caution - only enable if assumptions hold true for your code. interface CompilerAssumptions {
// Object.assign doesn't trigger getters
pureGetters ?: boolean ;
// Object rest doesn't include symbols
objectRestNoSymbols ?: boolean ;
// Class fields can use assignment (not defineProperty)
setPublicClassFields ?: boolean ;
// Don't preserve function.length
ignoreFunctionLength ?: boolean ;
// document.all is not used
noDocumentAll ?: boolean ;
}
Example: const result = transformSync ( 'app.js' , code , {
assumptions: {
setPublicClassFields: true ,
objectRestNoSymbols: true
},
target: 'es2015'
});
Helper Functions
Configure how runtime helper functions are injected. interface Helpers {
mode ?: 'Runtime' | 'External' ; // default: 'Runtime'
}
Runtime mode (default): // Helpers are imported from @oxc-project/runtime
const result = transformSync ( 'app.js' , '({ ...x })' , {
target: 'es2015' ,
helpers: { mode: 'Runtime' }
});
// Output: import _objectSpread from "@oxc-project/runtime/helpers/objectSpread2";
// _objectSpread({}, x);
External mode: // Helpers accessed from global babelHelpers object
const result = transformSync ( 'app.js' , '({ ...x })' , {
target: 'es2015' ,
helpers: { mode: 'External' }
});
// Output: babelHelpers.objectSpread2({}, x);
Plugins
Replace global variables with constant expressions at compile time. const result = transformSync ( 'app.js' ,
'if (process.env.NODE_ENV === "production") { /* ... */ }' ,
{
define: {
'process.env.NODE_ENV' : '"development"'
}
}
);
// The if block is removed (dead code elimination)
inject
Record<string, string | [string, string]>
Automatically import identifiers from modules. const result = transformSync ( 'app.js' ,
'const x = Object.assign({}, y);' ,
{
inject: {
'Object.assign' : 'object-assign'
}
}
);
// Output: import $inject_Object_assign from "object-assign";
// const x = $inject_Object_assign({}, y);
Named imports: {
inject : {
Promise : [ 'es6-promise' , 'Promise' ]
}
}
// Output: import { Promise } from "es6-promise";
Configure decorator transformation. interface DecoratorOptions {
// Use legacy decorators (pre-TC39 standardization)
legacy ?: boolean ; // default: false
// Emit decorator metadata (TypeScript)
emitDecoratorMetadata ?: boolean ; // default: false
}
Example: const result = transformSync ( 'app.ts' , code , {
decorator: {
legacy: true ,
emitDecoratorMetadata: true
}
});
Third-party plugin configurations. interface PluginsOptions {
// styled-components plugin
styledComponents ?: StyledComponentsOptions ;
// Escape template literal tags
taggedTemplateEscape ?: boolean ;
}
styled-components: const result = transformSync ( 'Button.js' , code , {
plugins: {
styledComponents: {
displayName: true ,
ssr: true ,
minify: true ,
transpileTemplateLiterals: true ,
pure: true ,
namespace: 'my-app'
}
}
});
The result of transformation, containing the transformed code, source maps, declarations, and any errors.
The transformed JavaScript code. Empty string if parsing failed. const { code } = transformSync ( 'app.ts' , sourceCode );
console . log ( code );
Source map for the transformed code. Only present if sourcemap: true. interface SourceMap {
version : number ;
sources : string [];
sourcesContent ?: string [];
names : string [];
mappings : string ;
file ?: string ;
sourceRoot ?: string ;
}
Generated .d.ts declaration file content. Only present if typescript.declaration is set and input is TypeScript. const result = transformSync ( 'lib.ts' , code , {
typescript: { declaration: {} }
});
console . log ( result . declaration ); // TypeScript declarations
Source map for the declaration file. Only present if both sourcemap and typescript.declaration are enabled.
Map of helper functions used during transformation and their import paths. const result = transformSync ( 'app.js' , '({ ...x })' , { target: 'es2015' });
console . log ( result . helpersUsed );
// { "objectSpread2": "@oxc-project/runtime/helpers/objectSpread2" }
Parse and transformation errors. Oxc’s parser recovers from errors, so code may be available even with errors present. if ( result . errors . length > 0 ) {
result . errors . forEach ( error => {
console . error ( error . message );
if ( error . codeframe ) console . error ( error . codeframe );
});
}
Common Use Cases
TypeScript to JavaScript
import { transformSync } from 'oxc-transform' ;
const tsCode = `
interface Config {
timeout: number;
}
export class ApiClient {
private config: Config;
constructor(config: Config) {
this.config = config;
}
async fetch<T>(url: string): Promise<T> {
// implementation
}
}
` ;
const result = transformSync ( 'client.ts' , tsCode , {
sourceType: 'module'
});
console . log ( result . code );
// TypeScript syntax removed, JavaScript remains
ES2020+ to ES2015
const modernJs = `
const user = { name: 'Alice', ...defaults };
const greeting = user?.name ?? 'Guest';
class Handler {
#private = 42;
static { console.log('static block'); }
}
` ;
const result = transformSync ( 'app.js' , modernJs , {
target: 'es2015' ,
sourceType: 'module'
});
console . log ( result . code );
// All modern syntax transformed to ES2015
const jsxCode = `
import { useState } from 'react';
export function Counter() {
const [count, setCount] = useState(0);
return (
<div className="counter">
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
` ;
const result = transformSync ( 'Counter.jsx' , jsxCode , {
jsx: {
runtime: 'automatic' ,
development: false
},
sourceType: 'module'
});
console . log ( result . code );
Environment Variables (Define Plugin)
const code = `
if (DEBUG) {
console.log('Debug mode enabled');
}
const apiUrl = API_URL;
` ;
const result = transformSync ( 'config.js' , code , {
define: {
DEBUG: 'false' ,
API_URL: '"https://api.example.com"'
}
});
// Debug block removed, API_URL replaced with string
const decoratedCode = `
@sealed
class Person {
@logged
name: string;
@validate
setName(@required newName: string) {
this.name = newName;
}
}
` ;
const result = transformSync ( 'person.ts' , decoratedCode , {
decorator: {
legacy: true ,
emitDecoratorMetadata: true
}
});
console . log ( result . code );
Generate Declaration Files
const libCode = `
export interface Options {
retries: number;
}
export function request(url: string, options?: Options): Promise<Response> {
// implementation
}
` ;
const result = transformSync ( 'api.ts' , libCode , {
typescript: {
declaration: {
stripInternal: true // Remove @internal declarations
}
},
sourcemap: true
});
console . log ( result . code ); // JavaScript
console . log ( result . declaration ); // .d.ts
console . log ( result . declarationMap ); // .d.ts.map
Use transformSync The synchronous API is faster for individual files as it avoids thread spawning overhead.
Set Specific Targets Only transform what’s necessary. Use target: 'esnext' to disable all transformations when targeting modern environments. // Only transform arrow functions and spread
{ target : 'es2017' }
// Transform everything
{ target : 'es2015' }
// No transformations
{ target : 'esnext' }
Enable Assumptions Assumptions can reduce code size but only use them if they’re safe for your codebase. {
assumptions : {
setPublicClassFields : true , // Smaller class field output
objectRestNoSymbols : true // Faster object spread
}
}
Source Maps in Production Only enable source maps when needed. They add processing overhead. const isDev = process . env . NODE_ENV === 'development' ;
const result = transformSync ( filename , code , {
sourcemap: isDev
});
Error Handling
import { transformSync , type OxcError } from 'oxc-transform' ;
function transform ( filename : string , code : string ) {
const result = transformSync ( filename , code , {
target: 'es2015' ,
jsx: { runtime: 'automatic' }
});
if ( result . errors . length > 0 ) {
console . error ( `Transformation errors in ${ filename } :` );
result . errors . forEach (( error : OxcError ) => {
console . error ( ` [ ${ error . severity } ] ${ error . message } ` );
error . labels . forEach ( label => {
if ( label . message ) {
console . error ( ` ${ label . message } at ${ label . start } : ${ label . end } ` );
}
});
if ( error . helpMessage ) {
console . log ( ` Help: ${ error . helpMessage } ` );
}
if ( error . codeframe ) {
console . error ( error . codeframe );
}
});
// Decide whether to use result.code or throw
if ( result . code === '' ) {
throw new Error ( 'Transformation failed' );
}
}
return result ;
}
Type Definitions
Full TypeScript definitions are included:
import type {
TransformOptions ,
TransformResult ,
TypeScriptOptions ,
JsxOptions ,
CompilerAssumptions ,
DecoratorOptions ,
HelperMode ,
SourceMap ,
OxcError
} from 'oxc-transform' ;
Parser API Parse JavaScript/TypeScript into an AST
Minifier API Minify JavaScript for production
Transformer Tool Learn more about the Oxc transformer
Node.js Integration Integrate Oxc into your Node.js workflow