Bun 的打包器 API 深受 esbuild 启发。从 esbuild 迁移到 Bun 的打包器应该相对无痛。本指南将简要解释为什么您可能考虑迁移到 Bun 的打包器,并为那些已经熟悉 esbuild API 的人提供并排 API 比较参考。
有一些行为差异需要注意。
NOTE
**默认打包。** 与 esbuild 不同,Bun 始终默认打包。这就是为什么在 Bun 示例中不需要 `--bundle` 标志。要逐个转译每个文件,请使用 `Bun.Transpiler`。NOTE
**它只是打包器。** 与 esbuild 不同,Bun 的打包器不包含内置的开发服务器或文件监听器。它只是打包器。打包器旨在与 `Bun.serve` 和其他运行时 API 结合使用以实现相同效果。因此,所有与 HTTP/文件监听相关的选项都不适用。性能
凭借注重性能的 API 和经过广泛优化的基于 Zig 的 JS/TS 解析器,Bun 的打包器在 esbuild 的 three.js 基准测试中比 esbuild 快 1.75 倍。
CLI API
Bun 和 esbuild 都提供命令行界面。
bash
# 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 | n/a | Bun 始终打包,使用 --no-bundle 禁用此行为。 |
--define:K=V | --define K=V | 小的语法差异;无冒号。esbuild --define:foo=barbun build --define foo=bar |
--external:<pkg> | --external <pkg> | 小的语法差异;无冒号。esbuild --external:reactbun build --external react |
--format | --format | Bun 目前支持 "esm" 和 "cjs",但计划支持更多模块格式。esbuild 默认为 "iife"。 |
--loader:.ext=loader | --loader .ext:loader | Bun 支持与 esbuild 不同的一组内置加载器;完整参考请参阅打包器 > 加载器。esbuild 加载器 dataurl、binary、base64、copy 和 empty 尚未实现。--loader 的语法略有不同。esbuild app.ts --bundle --loader:.svg=textbun build app.ts --loader .svg:text |
--minify | --minify | 无差异 |
--outdir | --outdir | 无差异 |
--outfile | --outfile | 无差异 |
--packages | --packages | 无差异 |
--platform | --target | 为与 tsconfig 保持一致而重命名为 --target。不支持 neutral。 |
--serve | n/a | 不适用 |
--sourcemap | --sourcemap | 无差异 |
--splitting | --splitting | 无差异 |
--target | n/a | 不支持。Bun 的打包器此时不执行语法降级。 |
--watch | --watch | 无差异 |
--allow-overwrite | n/a | 不允许覆盖 |
--analyze | n/a | 不支持 |
--asset-names | --asset-naming | 为与 JS API 中的 naming 保持一致而重命名 |
--banner | --banner | 仅适用于 js 打包 |
--footer | --footer | 仅适用于 js 打包 |
--certfile | n/a | 不适用 |
--charset=utf8 | n/a | 不支持 |
--chunk-names | --chunk-naming | 为与 JS API 中的 naming 保持一致而重命名 |
--color | n/a | 始终启用 |
--drop | --drop | |
--entry-names | --entry-naming | 为与 JS API 中的 naming 保持一致而重命名 |
--global-name | n/a | 不适用,Bun 此时不支持 iife 输出 |
--ignore-annotations | --ignore-dce-annotations | |
--inject | n/a | 不支持 |
--jsx | --jsx-runtime <runtime> | 支持 "automatic"(使用 jsx 转换)和 "classic"(使用 React.createElement) |
--jsx-dev | n/a | Bun 从 tsconfig.json 读取 compilerOptions.jsx 以确定默认值。如果 compilerOptions.jsx 为 "react-jsx",或如果 NODE_ENV=production,Bun 将使用 jsx 转换。否则,它使用 jsxDEV。打包器不支持 preserve。 |
--jsx-factory | --jsx-factory | |
--jsx-fragment | --jsx-fragment | |
--jsx-import-source | --jsx-import-source | |
--jsx-side-effects | n/a | JSX 始终假定为无副作用 |
--keep-names | n/a | 不支持 |
--keyfile | n/a | 不适用 |
--legal-comments | n/a | 不支持 |
--log-level | n/a | 不支持。这可以在 bunfig.toml 中设置为 logLevel。 |
--log-limit | n/a | 不支持 |
--log-override:X=Y | n/a | 不支持 |
--main-fields | n/a | 不支持 |
--mangle-cache | n/a | 不支持 |
--mangle-props | n/a | 不支持 |
--mangle-quoted | n/a | 不支持 |
--metafile | n/a | 不支持 |
--minify-whitespace | --minify-whitespace | |
--minify-identifiers | --minify-identifiers | |
--minify-syntax | --minify-syntax | |
--out-extension | n/a | 不支持 |
--outbase | --root | |
--preserve-symlinks | n/a | 不支持 |
--public-path | --public-path | |
--pure | n/a | 不支持 |
--reserve-props | n/a | 不支持 |
--resolve-extensions | n/a | 不支持 |
--servedir | n/a | 不适用 |
--source-root | n/a | 不支持 |
--sourcefile | n/a | 不支持。Bun 尚不支持 stdin 输入。 |
--sourcemap | --sourcemap | 无差异 |
--sources-content | n/a | 不支持 |
--supported | n/a | 不支持 |
--tree-shaking | n/a | 始终为 true |
--tsconfig | --tsconfig-override | |
--version | n/a | 运行 bun --version 查看 Bun 版本。 |
JavaScript API
| esbuild.build() | Bun.build() | 注释 |
|---|---|---|
absWorkingDir | n/a | 始终设置为 process.cwd() |
alias | n/a | 不支持 |
allowOverwrite | n/a | 始终为 false |
assetNames | naming.asset | 使用与 esbuild 相同的模板语法,但必须显式包含 [ext]。ts<br/>Bun.build({<br/> entrypoints: ["./index.tsx"],<br/> naming: {<br/> asset: "[name].[ext]",<br/> },<br/>});<br/> |
banner | n/a | 不支持 |
bundle | n/a | 始终为 true。使用 Bun.Transpiler 转译而不打包。 |
charset | n/a | 不支持 |
chunkNames | naming.chunk | 使用与 esbuild 相同的模板语法,但必须显式包含 [ext]。ts<br/>Bun.build({<br/> entrypoints: ["./index.tsx"],<br/> naming: {<br/> chunk: "[name].[ext]",<br/> },<br/>});<br/> |
color | n/a | Bun 在构建结果的 logs 属性中返回日志。 |
conditions | n/a | 不支持。导出条件优先级由 target 确定。 |
define | define | |
drop | n/a | 不支持 |
entryNames | naming 或 naming.entry | Bun 支持可以是字符串或对象的 naming 键。使用与 esbuild 相同的模板语法,但必须显式包含 [ext]。ts<br/>Bun.build({<br/> entrypoints: ["./index.tsx"],<br/> // 当为字符串时,这等同于 entryNames<br/> naming: "[name].[ext]",<br/><br/> // 细粒度命名选项<br/> naming: {<br/> entry: "[name].[ext]",<br/> asset: "[name].[ext]",<br/> chunk: "[name].[ext]",<br/> },<br/>});<br/> |
entryPoints | entrypoints | 大小写差异 |
external | external | 无差异 |
footer | n/a | 不支持 |
format | format | 目前仅支持 "esm"。计划支持 "cjs" 和 "iife"。 |
globalName | n/a | 不支持 |
ignoreAnnotations | n/a | 不支持 |
inject | n/a | 不支持 |
jsx | jsx | 在 JS API 中不支持,在 tsconfig.json 中配置 |
jsxDev | jsxDev | 在 JS API 中不支持,在 tsconfig.json 中配置 |
jsxFactory | jsxFactory | 在 JS API 中不支持,在 tsconfig.json 中配置 |
jsxFragment | jsxFragment | 在 JS API 中不支持,在 tsconfig.json 中配置 |
jsxImportSource | jsxImportSource | 在 JS API 中不支持,在 tsconfig.json 中配置 |
jsxSideEffects | jsxSideEffects | 在 JS API 中不支持,在 tsconfig.json 中配置 |
keepNames | n/a | 不支持 |
legalComments | n/a | 不支持 |
loader | loader | Bun 支持与 esbuild 不同的一组内置加载器;完整参考请参阅打包器 > 加载器。esbuild 加载器 dataurl、binary、base64、copy 和 empty 尚未实现。 |
logLevel | n/a | 不支持 |
logLimit | n/a | 不支持 |
logOverride | n/a | 不支持 |
mainFields | n/a | 不支持 |
mangleCache | n/a | 不支持 |
mangleProps | n/a | 不支持 |
mangleQuoted | n/a | 不支持 |
metafile | n/a | 不支持 |
minify | minify | 在 Bun 中,minify 可以是布尔值或对象。ts<br/>await Bun.build({<br/> entrypoints: ['./index.tsx'],<br/> // 启用所有压缩<br/> minify: true<br/><br/> // 细粒度选项<br/> minify: {<br/> identifiers: true,<br/> syntax: true,<br/> whitespace: true<br/> }<br/>})<br/> |
minifyIdentifiers | minify.identifiers | 请参阅 minify |
minifySyntax | minify.syntax | 请参阅 minify |
minifyWhitespace | minify.whitespace | 请参阅 minify |
nodePaths | n/a | 不支持 |
outExtension | n/a | 不支持 |
outbase | root | 不同的名称 |
outdir | outdir | 无差异 |
outfile | outfile | 无差异 |
packages | n/a | 不支持,使用 external |
platform | target | 支持 "bun"、"node" 和 "browser"(默认)。不支持 "neutral"。 |
plugins | plugins | Bun 的插件 API 是 esbuild 的子集。一些 esbuild 插件可以直接与 Bun 一起工作。 |
preserveSymlinks | n/a | 不支持 |
publicPath | publicPath | 无差异 |
pure | n/a | 不支持 |
reserveProps | n/a | 不支持 |
resolveExtensions | n/a | 不支持 |
sourceRoot | n/a | 不支持 |
sourcemap | sourcemap | 支持 "inline"、"external" 和 "none" |
sourcesContent | n/a | 不支持 |
splitting | splitting | 无差异 |
stdin | n/a | 不支持 |
supported | n/a | 不支持 |
target | n/a | 不支持语法降级 |
treeShaking | n/a | 始终为 true |
tsconfig | n/a | 不支持 |
write | n/a | 如果设置了 outdir/outfile 则为 true,否则为 false |
插件 API
Bun 的插件 API 设计为与 esbuild 兼容。Bun 不支持 esbuild 的整个插件 API 表面,但实现了核心功能。许多第三方 esbuild 插件可以直接与 Bun 一起工作。
NOTE
长期来看,我们的目标是与 esbuild 的 API 功能对等,因此如果某些内容不起作用,请提交问题以帮助我们确定优先级。Bun 和 esbuild 中的插件使用构建器对象定义。
ts
import type { BunPlugin } from "bun";
const myPlugin: BunPlugin = {
name: "my-plugin",
setup(builder) {
// 定义插件
},
};构建器对象提供了一些方法用于挂钩到打包过程的部分。Bun 实现了 onResolve 和 onLoad;它尚未实现 esbuild 钩子 onStart、onEnd 和 onDispose,以及 resolve 工具。initialOptions 部分实现,为只读且仅有 esbuild 选项的子集;请改用 config(相同但使用 Bun 的 BuildConfig 格式)。
ts
import type { BunPlugin } from "bun";
const myPlugin: BunPlugin = {
name: "my-plugin",
setup(builder) {
builder.onResolve(
{
/* onResolve.options */
},
args => {
return {
/* onResolve.results */
};
},
);
builder.onLoad(
{
/* onLoad.options */
},
args => {
return {
/* onLoad.results */
};
},
);
},
};onResolve
选项
- 🟢 `filter`
- 🟢 `namespace`
参数
- 🟢 `path`
- 🟢 `importer`
- 🔴 `namespace`
- 🔴 `resolveDir`
- 🔴 `kind`
- 🔴 `pluginData`
结果
- 🟢 `namespace`
- 🟢 `path`
- 🔴 `errors`
- 🔴 `external`
- 🔴 `pluginData`
- 🔴 `pluginName`
- 🔴 `sideEffects`
- 🔴 `suffix`
- 🔴 `warnings`
- 🔴 `watchDirs`
- 🔴 `watchFiles`
onLoad
选项
- 🟢 `filter`
- 🟢 `namespace`
参数
- 🟢 `path`
- 🔴 `namespace`
- 🔴 `suffix`
- 🔴 `pluginData`
结果
- 🟢 `contents`
- 🟢 `loader`
- 🔴 `errors`
- 🔴 `pluginData`
- 🔴 `pluginName`
- 🔴 `resolveDir`
- 🔴 `warnings`
- 🔴 `watchDirs`
- 🔴 `watchFiles`