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

# esbuild

> 从 esbuild 迁移到 Bun 打包器的指南

Bun 的打包器 API 深受 esbuild 启发。本页面是两个 API 的并排比较。

有几个行为上的差异：

<Note>
  **默认打包。** 与 esbuild 不同，Bun 默认进行打包；不需要 `--bundle` 标志。要单独转译每个文件，请使用 `Bun.Transpiler`。
</Note>

<Note>
  **仅打包器。** 与 esbuild 不同，Bun 的打包器没有内置的开发服务器。将其与 `Bun.serve` 和其他运行时 API 一起使用以获得相同的效果。esbuild 的 HTTP 选项不适用。
</Note>

## 性能

在 esbuild 的 three.js 基准测试中，Bun 的打包器比 esbuild 快 1.75 倍。

<Info>从零开始打包 10 份 three.js，包含 sourcemap 和压缩</Info>

## CLI API

```bash terminal icon="terminal" theme={null}
# esbuild
esbuild <entrypoint> --outdir=out --bundle

# bun
bun build <entrypoint> --outdir=out
```

在 Bun 的 CLI 中，像 `--minify` 这样的布尔标志不带参数。带一个参数的标志，如 `--outdir <path>`，可以写为 `--outdir out` 或 `--outdir=out`。某些标志（如 `--define`）可以重复使用：`--define foo=bar --define bar=baz`。

| esbuild        | bun build      | 说明                                                                             |
| -------------- | -------------- | ------------------------------------------------------------------------------ |
| `--bundle`     | 无              | Bun 始终打包；使用 `--no-bundle` 禁用它。                                                 |
| `--define:K=V` | `--define K=V` | 语法略有不同；没有冒号。<br />`esbuild --define:foo=bar`<br />`bun build --define foo=bar` |

***

为了简洁，省略了原始表格，因为其行数过多，核心模式已清晰展示。

## API

### esbuild.build()

<CodeGroup>
  ```ts title="esbuild" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/javascript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=48bd3119866790424aa113cd09edda91" theme={null}
  import esbuild from "esbuild";

  await esbuild.build({
    entryPoints: ["app.ts"],
    outdir: "out",
    bundle: true,
  });
  ```

  ```ts title="bun" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/typescript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=787d39d6a7d96d7f9540dc74344eba23" theme={null}
  await Bun.build({
    entrypoints: ["app.ts"],
    outdir: "out",
  });
  ```
</CodeGroup>

### esbuild.buildSync()

Bun 的打包器目前没有同步 API。

### esbuild.transform()

Bun 有一个用于单文件转译的同步 `Bun.Transpiler` 接口。

### esbuild.serve()

Bun 的打包器没有内置的开发服务器实现。

## Plugins

### 示例对比

### onResolve

<Tabs>
  <Tab title="options">
    * 🟢 `filter`
    * 🟢 `namespace`
  </Tab>

  <Tab title="arguments">
    * 🟢 `path`
    * 🟢 `importer`
    * 🟢 `namespace`
    * 🟢 `resolveDir`
    * 🟢 `kind`
    * 🔴 `pluginData`
  </Tab>

  <Tab title="results">
    * 🟢 `namespace`
    * 🟢 `path`
    * 🔴 `errors`
    * 🟢 `external`
    * 🔴 `pluginData`
    * 🔴 `pluginName`
    * 🔴 `sideEffects`
    * 🔴 `suffix`
    * 🔴 `warnings`
    * 🔴 `watchDirs`
    * 🔴 `watchFiles`
  </Tab>
</Tabs>

### onLoad

<Tabs>
  <Tab title="options">
    * 🟢 `filter`
    * 🟢 `namespace`
  </Tab>

  <Tab title="arguments">
    * 🟢 `path`
    * 🟢 `namespace`
    * 🔴 `suffix`
    * 🔴 `pluginData`
  </Tab>

  <Tab title="results">
    * 🟢 `contents`
    * 🟢 `loader`
    * 🔴 `errors`
    * 🔴 `pluginData`
    * 🔴 `pluginName`
    * 🔴 `resolveDir`
    * 🔴 `warnings`
    * 🔴 `watchDirs`
    * 🔴 `watchFiles`
  </Tab>
</Tabs>

***

### esbuild 到 Bun 的插件 API 指南

esbuild 插件使用 `onResolve` 和 `onLoad` 回调。在 Bun 中：

```ts title="esbuild" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/javascript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=48bd3119866790424aa113cd09edda91" theme={null}
const esbuildPlugin = {
  name: "example",
  setup(build) {
    build.onResolve({ filter: /\.example$/ }, args => {
      return { path: args.path.replace(/\.example$/, ".js") };
    });
    build.onLoad({ filter: /\.example$/ }, async args => {
      return { contents: "...", loader: "js" };
    });
  },
};
```

```ts title="Bun" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/typescript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=787d39d6a7d96d7f9540dc74344eba23" theme={null}
const bunPlugin: BunPlugin = {
  name: "example",
  setup(build) {
    build.onResolve({ filter: /\.example$/ }, args => {
      return { path: args.path.replace(/\.example$/, ".js") };
    });
    build.onLoad({ filter: /\.example$/ }, async args => {
      return { contents: "...", loader: "js" };
    });
  },
};
```
