# How to Use Bun.Transpiler for Runtime Code Transformation: A Complete Guide

> Learn to use Bun.Transpiler for runtime code transformation. This guide explains how to convert TypeScript and JSX to JavaScript instantly with Bun's fast engine.

- Repository: [Bun/bun](https://github.com/oven-sh/bun)
- Tags: how-to-guide
- Published: 2026-02-28

---

**Bun.Transpiler is a high-performance JavaScript API that transforms TypeScript and JSX into vanilla JavaScript at runtime using Bun's Zig-based transpiler engine, supporting both synchronous and asynchronous execution patterns.**

The `Bun.Transpiler` class in the oven-sh/bun repository provides direct access to Bun's internal transpilation pipeline without invoking the full bundler. This runtime API allows developers to transform, scan, and analyze JavaScript or TypeScript source code on demand, leveraging the same high-performance Zig implementation that powers Bun's build system.

## Architecture and Implementation

`Bun.Transpiler` is a thin JavaScript wrapper around the core Transpiler implementation written in Zig. The class constructs a transpiler instance with user-provided options—such as **loader**, **target**, and **macros**—and delegates all public methods to the underlying Zig engine located in `src/transpiler.zig`.

The core implementation handles entry-point resolution, parsing via `js_parser`, macro execution, printing via `js_printer`, and optional source-map generation. When you instantiate `new Bun.Transpiler(opts)`, the JavaScript bridge creates a Zig `Transpiler` instance through `Transpiler.init`, establishing the configuration context for all subsequent operations.

## Core Transformation Methods

### Synchronous Transformation with transformSync

**`transformSync`** executes the transpilation pipeline on the current thread, making it ideal for small, occasional transforms where thread-pool overhead would be wasteful. The method accepts source code and an optional loader override, then immediately processes the input through `parse` → `print` → `options.TransformResult` according to the implementation in `src/transpiler.zig`.

```typescript
import { readFileSync } from "fs";

const transpiler = new Bun.Transpiler({ loader: "tsx" });

const source = readFileSync("./example.tsx", "utf8");
const js = transpiler.transformSync(source);   // → plain JS string
console.log(js);

```

### Asynchronous Transformation with transform

**`transform`** schedules work on Bun's internal thread-pool, enabling non-blocking execution for batch processing or hot-reloading scenarios. Each job runs on its own event loop and executes the same `parse` and `print` pipeline in isolation, allowing heavy workloads to scale across CPU cores. The thread-pool dispatch occurs through `processResolveQueue` as implemented in the Zig source.

```typescript
const transpiler = new Bun.Transpiler({ loader: "jsx" });

(async () => {
  const js = await transpiler.transform(`
    const el = <h1>Hello, world!</h1>;
    export default el;
  `);
  console.log(js);
})();

```

### Static Analysis with scan and scanImports

For scenarios requiring metadata without code emission, **`.scan()`** and **`.scanImports()`** walk the AST to collect import and export information. These methods use the same parser infrastructure as the transform pipeline but skip the printing phase, returning structured metadata about dependencies.

```typescript
const transpiler = new Bun.Transpiler({ loader: "tsx" });

const code = `
  import React from "react";
  const data = require("./data.json");
  export const name = "Bun";
`;

const meta = transpiler.scan(code);
console.log(meta.exports); // ["name"]
console.log(meta.imports); // [{kind:"import-statement", path:"react"}, …]

```

For faster import-only analysis, **`.scanImports()`** provides a streamlined interface:

```typescript
const imports = new Bun.Transpiler({ loader: "tsx" }).scanImports(`
  import foo from "./foo";
  const bar = require("./bar");
`);
console.log(imports);
// → [{kind:"import-statement", path:"./foo"}, {kind:"require-call", path:"./bar"}]

```

## Advanced Runtime Transformation Patterns

### Overriding Loaders Per-Call

While the transpiler instance maintains default options, individual calls can override the loader. This allows a single `Bun.Transpiler` instance to handle multiple file types without reconstruction.

```typescript
const transpiler = new Bun.Transpiler({ loader: "js" });

const result = transpiler.transformSync("<div>Hello</div>", "tsx");
console.log(result);   // JSX compiled as TSX

```

### Macro Support

When macros are configured, the transpiler spawns a separate JavaScript runtime on the worker thread. Macro state lives in a shared `js_ast.Macro.MacroContext`, enabling compile-time code generation and transformation.

```typescript
const transpiler = new Bun.Transpiler({
  loader: "tsx",
  macro: {
    "my-macro": "./macros/my-macro.tsx"
  }
});

const result = await transpiler.transform(`
  import { hello } from "my-macro";
  console.log(hello);
`);

```

## Performance Considerations: Sync vs Async

Choosing between synchronous and asynchronous transformation depends on workload characteristics:

- **Use `transformSync`** for small, occasional transforms or when blocking the event loop is acceptable. This avoids the thread-pool scheduling overhead and executes immediately in `src/transpiler.zig` starting at line 1495.

- **Use `transform`** for batch processing, hot-reloading servers, or when processing multiple files concurrently. The thread-pool utilization ensures the main thread remains non-blocking while Zig workers handle the heavy lifting across available cores.

## Summary

- **Bun.Transpiler** provides direct runtime access to Bun's Zig-based transpilation engine without invoking the full bundler.
- **`transformSync`** runs on the current thread for immediate, low-overhead transformation, while **`transform`** dispatches to Bun's thread-pool for concurrent processing.
- **`scan`** and **`scanImports`** extract import/export metadata without generating code, useful for dependency analysis and linting.
- **Macro support** executes in isolated JavaScript runtimes on worker threads, managed through `js_ast.Macro.MacroContext`.
- The implementation resides primarily in `src/transpiler.zig`, with user-facing documentation in `docs/runtime/transpiler.mdx` and TypeScript definitions in [`packages/bun-types/bun.d.ts`](https://github.com/oven-sh/bun/blob/main/packages/bun-types/bun.d.ts).

## Frequently Asked Questions

### How does Bun.Transpiler differ from Bun's bundler?

Bun.Transpiler exposes the underlying transformation engine directly, allowing runtime code transformation without entry-point resolution, dependency graph building, or output bundling. While the bundler orchestrates full builds, the Transpiler class focuses on single-file transformation and static analysis as implemented in `src/transpiler.zig`.

### Can I use Bun.Transpiler in a production server environment?

Yes, the asynchronous `transform` method is specifically designed for server use cases. By utilizing Bun's thread-pool through `processResolveQueue`, it prevents heavy transpilation tasks from blocking the main event loop, making it suitable for hot-reloading development servers or on-demand transformation in production APIs.

### What file types does Bun.Transpiler support?

The Transpiler accepts any loader supported by Bun, including `"js"`, `"jsx"`, `"ts"`, `"tsx"`, and others defined in [`packages/bun-types/bun.d.ts`](https://github.com/oven-sh/bun/blob/main/packages/bun-types/bun.d.ts). You can set a default loader in the constructor or override it per-call, allowing flexible handling of mixed file types within a single instance.

### How are errors handled during transformation?

Errors thrown during parsing or transformation propagate from the Zig implementation to the JavaScript caller. The test suite in [`test/regression/issue/012039.test.ts`](https://github.com/oven-sh/bun/blob/main/test/regression/issue/012039.test.ts) specifically validates error handling behavior in `transformSync`, ensuring that syntax errors and invalid configurations produce actionable JavaScript exceptions.