Transpiler
Use Bun's transpiler to transpile JavaScript and TypeScript code
Bun exposes its internal transpiler via the Bun.Transpiler class. To create an instance of Bun's transpiler:
const transpiler = new Bun.Transpiler({
loader: "tsx", // "js | "jsx" | "ts" | "tsx"
});.transformSync()
Transpile code synchronously with the .transformSync() method. Modules are not resolved and the code is not executed. The result is a string of vanilla JavaScript code.
const transpiler = new Bun.Transpiler({
loader: 'tsx',
});
const code = `
import * as whatever from "./whatever.ts"
export function Home(props: {title: string}){
return <p>{props.title}</p>;
}`;
const result = transpiler.transformSync(code);To override the default loader specified in the new Bun.Transpiler() constructor, pass a second argument to .transformSync().
transpiler.transformSync("<div>hi!</div>", "tsx");.transform()
The transform() method is an async version of .transformSync() that returns a Promise<string>.
const transpiler = new Bun.Transpiler({ loader: "jsx" });
const result = await transpiler.transform("<div>hi!</div>");
console.log(result);Unless you're transpiling many large files, you should probably use Bun.Transpiler.transformSync. The cost of the threadpool will often take longer than actually transpiling code.
await transpiler.transform("<div>hi!</div>", "tsx");.scan()
The Transpiler instance can also scan some source code and return a list of its imports and exports, plus additional metadata about each one. Type-only imports and exports are ignored.
const transpiler = new Bun.Transpiler({
loader: "tsx",
});
const code = `
import React from 'react';
import type {ReactNode} from 'react';
const val = require('./cjs.js')
import('./loader');
export const name = "hello";
`;
const result = transpiler.scan(code);Each import in the imports array has a path and kind. Bun categories imports into the following kinds:
import-statement:import React from 'react'require-call:const val = require('./cjs.js')require-resolve:require.resolve('./cjs.js')dynamic-import:import('./loader')import-rule:@import 'foo.css'url-token:url('./foo.png')
.scanImports()
For performance-sensitive code, you can use the .scanImports() method to get a list of imports. It's faster than .scan() (especially for large files) but marginally less accurate due to some performance optimizations.
const transpiler = new Bun.Transpiler({
loader: "tsx",
});
const code = `
import React from 'react';
import type {ReactNode} from 'react';
const val = require('./cjs.js')
import('./loader');
export const name = "hello";
`;
const result = transpiler.scanImports(code);Reference
type Loader = "jsx" | "js" | "ts" | "tsx";
interface TranspilerOptions {
// Replace key with value. Value must be a JSON string.
// { "process.env.NODE_ENV": "\"production\"" }
define?: Record<string, string>,
// Default loader for this transpiler
loader?: Loader,
// Default platform to target
// This affects how import and/or require is used
target?: "browser" | "bun" | "node",
// Specify a tsconfig.json file as stringified JSON or an object
// Use this to set a custom JSX factory, fragment, or import source
// For example, if you want to use Preact instead of React. Or if you want to use Emotion.
tsconfig?: string | TSConfig,
// Replace imports with macros
macro?: MacroMap,
// Specify a set of exports to eliminate
// Or rename certain exports
exports?: {
eliminate?: string[];
replace?: Record<string, string>;
},
// Whether to remove unused imports from transpiled file
// Default: false
trimUnusedImports?: boolean,
// Whether to enable a set of JSX optimizations
// jsxOptimizationInline ...,
// Experimental whitespace minification
minifyWhitespace?: boolean,
// Whether to inline constant values
// Typically improves performance and decreases bundle size
// Default: true
inline?: boolean,
}
// Map import paths to macros
interface MacroMap {
// {
// "react-relay": {
// "graphql": "bun-macro-relay/bun-macro-relay.tsx"
// }
// }
[packagePath: string]: {
[importItemName: string]: string,
},
}
class Bun.Transpiler {
constructor(options: TranspilerOptions)
transform(code: string, loader?: Loader): Promise<string>
transformSync(code: string, loader?: Loader): string
scan(code: string): {exports: string[], imports: Import}
scanImports(code: string): Import[]
}
type Import = {
path: string,
kind:
// import foo from 'bar'; in JavaScript
| "import-statement"
// require("foo") in JavaScript
| "require-call"
// require.resolve("foo") in JavaScript
| "require-resolve"
// Dynamic import() in JavaScript
| "dynamic-import"
// @import() in CSS
| "import-rule"
// url() in CSS
| "url-token"
// The import was injected by Bun
| "internal"
// Entry point (not common)
| "entry-point-build"
| "entry-point-run"
}
const transpiler = new Bun.Transpiler({ loader: "jsx" });