> ## Documentation Index
> Fetch the complete documentation index at: https://bun.zhcndoc.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 转译器

> 使用 Bun 的转译器来转译 JavaScript 和 TypeScript 代码

Bun 通过 `Bun.Transpiler` 类暴露其内部转译器。要创建一个 Bun 转译器的实例：

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
const transpiler = new Bun.Transpiler({
  loader: "tsx", // "js" | "jsx" | "ts" | "tsx"
});
```

***

## `.transformSync()`

使用 `.transformSync()` 方法同步转译代码。模块不会被解析，代码也不会被执行。结果是一个纯净的 JavaScript 代码字符串。

<CodeGroup>
  ```ts transpile.ts icon="https://mintcdn.com/bun-zhcndoc/cnUTwgMuf4cCrwC-/icons/typescript.svg?fit=max&auto=format&n=cnUTwgMuf4cCrwC-&q=85&s=e7767043c9e885c34f2d6c8fe2a95217"  theme={"theme":{"light":"github-light","dark":"dracula"}}
  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);

  ```

  ```ts output theme={"theme":{"light":"github-light","dark":"dracula"}}
  import { __require as require } from "bun:wrap";
  import * as JSX from "react/jsx-dev-runtime";
  var jsx = require(JSX).jsxDEV;

  export default jsx(
    "div",
    {
      children: "hi!",
    },
    undefined,
    false,
    undefined,
    this,
  );
  ```
</CodeGroup>

要覆盖 `new Bun.Transpiler()` 构造函数中指定的默认加载器，可以给 `.transformSync()` 传入第二个参数。

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
transpiler.transformSync("<div>hi!</div>", "tsx");
```

<Accordion title="细节说明">
  当调用 `.transformSync` 时，转译器会在当前执行代码的相同线程中运行。

  如果使用了宏，它将在与转译器相同的线程中运行，但在一个独立的事件循环中，与应用程序的其余部分分开。当前，宏与普通代码之间共享全局变量，这意味着可以（但不推荐）在宏和普通代码间共享状态。试图在宏外部使用 AST 节点是未定义行为。
</Accordion>

***

## `.transform()`

`transform()` 方法是 `.transformSync()` 的异步版本，返回一个 `Promise<string>`。

```js theme={"theme":{"light":"github-light","dark":"dracula"}}
const transpiler = new Bun.Transpiler({ loader: "jsx" });
const result = await transpiler.transform("<div>hi!</div>");
console.log(result);
```

除非你要转译大量大文件，否则通常建议使用 `Bun.Transpiler.transformSync`。使用线程池的开销往往比实际转译代码花费的时间更久。

```ts theme={"theme":{"light":"github-light","dark":"dracula"}}
await transpiler.transform("<div>hi!</div>", "tsx");
```

<Accordion title="细节说明">
  `.transform()` 方法会在 Bun 的工作线程池中运行转译器，因此如果调用 100 次，会在 `Math.floor($cpu_count * 0.8)` 个线程间并行运行，不会阻塞主 JavaScript 线程。

  如果代码使用了宏，可能会在该新线程中启动 Bun JavaScript 运行时环境的新实例。
</Accordion>

## `.scan()`

`Transpiler` 实例还可以扫描某段源代码，返回其导入和导出列表及每个项的附加元数据。[仅类型](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export) 的导入和导出会被忽略。

<CodeGroup>
  ```ts example.ts icon="https://mintcdn.com/bun-zhcndoc/cnUTwgMuf4cCrwC-/icons/typescript.svg?fit=max&auto=format&n=cnUTwgMuf4cCrwC-&q=85&s=e7767043c9e885c34f2d6c8fe2a95217" theme={"theme":{"light":"github-light","dark":"dracula"}}
  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);
  ```

  ```json output theme={"theme":{"light":"github-light","dark":"dracula"}}
  {
    "exports": ["name"],
    "imports": [
      {
        "kind": "import-statement",
        "path": "react"
      },
      {
        "kind": "import-statement",
        "path": "remix"
      },
      {
        "kind": "dynamic-import",
        "path": "./loader"
      }
    ]
  }
  ```
</CodeGroup>

`imports` 数组中的每个导入项都有 `path` 和 `kind`。Bun 将导入分类如下：

* `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()`

对于性能敏感的代码，可以使用 `.scanImports()` 方法获取导入列表。由于一些性能优化，它比 `.scan()` 更快（尤其是大型文件），但准确度略低。

<CodeGroup>
  ```ts example.ts icon="https://mintcdn.com/bun-zhcndoc/cnUTwgMuf4cCrwC-/icons/typescript.svg?fit=max&auto=format&n=cnUTwgMuf4cCrwC-&q=85&s=e7767043c9e885c34f2d6c8fe2a95217" theme={"theme":{"light":"github-light","dark":"dracula"}}
  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);
  ```

  ```json results icon="file-json" theme={"theme":{"light":"github-light","dark":"dracula"}}
  [
    {
      "kind": "import-statement",
      "path": "react"
    },
    {
      "kind": "require-call",
      "path": "./cjs.js"
    },
    {
      "kind": "dynamic-import",
      "path": "./loader"
    }
  ]
  ```
</CodeGroup>

***

## 参考

```ts See Typescript Definitions expandable theme={"theme":{"light":"github-light","dark":"dracula"}}
type Loader = "jsx" | "js" | "ts" | "tsx";

interface TranspilerOptions {
  // 替换键为值，值必须是 JSON 字符串。
  // { "process.env.NODE_ENV": "\"production\"" }
  define?: Record<string, string>,

  // 此转译器的默认加载器
  loader?: Loader,

  // 默认目标平台
  // 影响 import 和/或 require 的使用方式
  target?: "browser" | "bun" | "node",

  // 指定 tsconfig.json 文件，字符串化的 JSON 或对象
  // 用于设置自定义的 JSX 工厂、片段或导入源
  // 例如，使用 Preact 替代 React，或使用 Emotion
  tsconfig?: string | TSConfig,

  // 用宏替换导入
  macro?: MacroMap,

  // 指定一组需剔除的导出项
  // 或重命名某些导出
  exports?: {
      eliminate?: string[];
      replace?: Record<string, string>;
  },

  // 是否从转译文件中移除未使用的导入
  // 默认: false
  trimUnusedImports?: boolean,

  // 是否启用一系列 JSX 优化
  // jsxOptimizationInline ...,

  // 实验性空白符压缩
  minifyWhitespace?: boolean,

  // 是否内联常量值
  // 通常提升性能并减少包大小
  // 默认: true
  inline?: boolean,
}

// 映射导入路径到宏
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:
  // JavaScript 中的 import foo from 'bar';
  | "import-statement"
  // JavaScript 中的 require("foo")
  | "require-call"
  // JavaScript 中的 require.resolve("foo")
  | "require-resolve"
  // JavaScript 中的动态 import()
  | "dynamic-import"
  // CSS 中的 @import()
  | "import-rule"
  // CSS 中的 url()
  | "url-token"
  // 导入是由 Bun 注入的
  | "internal"
  // 入口点（不常见）
  | "entry-point-build"
  | "entry-point-run"
}

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