esbuild
从 esbuild 迁移到 Bun 的打包器指南
Bun 的打包器 API 深受 esbuild 启发。本页面对这两个 API 进行了并列比较。
有一些行为有所不同:
性能
在 esbuild 的 three.js 基准测试中,Bun 的打包器速度比 esbuild 快 1.75 倍。
CLI API
terminal
# 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 | 语法略有不同;没有冒号。esbuild --define:foo=barbun build --define foo=bar |
--external:<pkg> | --external <pkg> | 语法略有不同;没有冒号。esbuild --external:reactbun build --external react |
--format | --format | Bun 支持 "esm"、"cjs" 和 "iife"。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 | 不适用 | 不适用 |
--sourcemap | --sourcemap | 支持 linked(未提供值时的默认值)、external、inline 和 none。不支持 esbuild 的 both。 |
--splitting | --splitting | 无差异 |
--target | 不适用 | 不支持。Bun 的打包器不会进行语法降级。 |
--watch | --watch | 无差异 |
--allow-overwrite | 不适用 | Bun 从不允许覆盖 |
--analyze | 不适用 | 不支持 |
--asset-names | --asset-naming | 为与 JS API 中的命名保持一致而重命名 |
--banner | --banner | 仅适用于 JS 包 |
--footer | --footer | 仅适用于 JS 包 |
--certfile | 不适用 | 不适用 |
--charset=utf8 | 不适用 | 不支持 |
--chunk-names | --chunk-naming | 为与 JS API 中的命名保持一致而重命名 |
--color | 不适用 | 始终启用 |
--drop | --drop | |
| 不适用 | --feature | Bun 特有。通过 import { feature } from "bun:bundle" 启用编译时死代码消除的功能标志 |
--entry-names | --entry-naming | 为与 JS API 中的命名保持一致而重命名 |
--global-name | 不适用 | 不支持 |
--ignore-annotations | --ignore-dce-annotations | |
--inject | 不适用 | 不支持 |
--jsx | --jsx-runtime <runtime> | 支持 "automatic"(使用 JSX 转换)和 "classic"(使用 React.createElement) |
--jsx-dev | 不适用 | 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 | --jsx-side-effects | |
--keep-names | --keep-names | |
--keyfile | 不适用 | 不适用 |
--legal-comments | 不适用 | 不支持 |
--log-level | 不适用 | 不支持。可以在 bunfig.toml 中将日志级别设置为 logLevel。 |
--log-limit | 不适用 | 不支持 |
--log-override:X=Y | 不适用 | 不支持 |
--main-fields | 不适用 | 不支持 |
--mangle-cache | 不适用 | 不支持 |
--mangle-props | 不适用 | 不支持 |
--mangle-quoted | 不适用 | 不支持 |
--metafile | --metafile | |
--minify-whitespace | --minify-whitespace | |
--minify-identifiers | --minify-identifiers | |
--minify-syntax | --minify-syntax | |
--out-extension | 不适用 | 不支持 |
--outbase | --root | |
--preserve-symlinks | 不适用 | 不支持 |
--public-path | --public-path | |
--pure | 不适用 | 不支持 |
--reserve-props | 不适用 | 不支持 |
--resolve-extensions | 不适用 | 不支持 |
--servedir | 不适用 | 不适用 |
--source-root | 不适用 | 不支持 |
--sourcefile | 不适用 | 不支持。Bun 不支持 stdin 输入。 |
--sources-content | 不适用 | 不支持 |
--supported | 不适用 | 不支持 |
--tree-shaking | 不适用 | 始终为 true。Bun 还会将 import() / require() 目标的导出进行摇树优化,仅保留导入代码读取的名称(请参阅 代码拆分);esbuild 会保留动态导入模块的所有导出。 |
--tsconfig | --tsconfig-override | |
--version | 不适用 | 运行 bun --version 查看 Bun 的版本。 |
JavaScript API
| esbuild.build() | Bun.build() | 备注 |
|---|---|---|
absWorkingDir | 不适用 | 始终设置为 process.cwd() |
alias | 不适用 | 不支持 |
allowOverwrite | 不适用 | 始终为 false |
assetNames | naming.asset | 使用与 esbuild 相同的模板语法,但必须明确包含 [ext]。ts<br/>Bun.build({<br/> entrypoints: ["./index.tsx"],<br/> naming: {<br/> asset: "[name].[ext]",<br/> },<br/>});<br/> |
banner | banner | 仅适用于 JS 包 |
bundle | 不适用 | 始终为 true。使用 Bun.Transpiler 可在不打包的情况下进行转译。 |
charset | 不适用 | 不支持 |
chunkNames | naming.chunk | 使用与 esbuild 相同的模板语法,但必须明确包含 [ext]。ts<br/>Bun.build({<br/> entrypoints: ["./index.tsx"],<br/> naming: {<br/> chunk: "[name].[ext]",<br/> },<br/>});<br/> |
color | 不适用 | Bun 会在构建结果的 logs 属性中返回日志。 |
conditions | conditions | 无差异 |
define | define | |
drop | drop | |
entryNames | naming 或 naming.entry | Bun 支持 naming 键,其值可以是字符串或对象。使用与 esbuild 相同的模板语法,但必须明确包含 [ext]。ts<br/>Bun.build({<br/> entrypoints: ["./index.tsx"],<br/> // when string, this is equivalent to entryNames<br/> naming: "[name].[ext]",<br/><br/> // granular naming options<br/> naming: {<br/> entry: "[name].[ext]",<br/> asset: "[name].[ext]",<br/> chunk: "[name].[ext]",<br/> },<br/>});<br/> |
entryPoints | entrypoints | 大小写不同 |
external | external | 无差异 |
footer | footer | 仅适用于 JS 包 |
format | format | 支持 "esm"、"cjs" 和 "iife"。 |
globalName | 不适用 | 不支持 |
ignoreAnnotations | ignoreDCEAnnotations | |
inject | 不适用 | 不支持 |
jsx | jsx.runtime | 支持 "automatic" 和 "classic" |
jsxDev | jsx.development | |
jsxFactory | jsx.factory | |
jsxFragment | jsx.fragment | |
jsxImportSource | jsx.importSource | |
jsxSideEffects | jsx.sideEffects | |
keepNames | minify.keepNames | |
legalComments | 不适用 | 不支持 |
loader | loader | Bun 支持的内置加载器与 esbuild 不同;请参阅 加载器。Bun 尚未实现 esbuild 的加载器 dataurl、binary、base64、copy 和 empty。 |
logLevel | 不适用 | 不支持 |
logLimit | 不适用 | 不支持 |
logOverride | 不适用 | 不支持 |
mainFields | 不适用 | 不支持 |
mangleCache | 不适用 | 不支持 |
mangleProps | 不适用 | 不支持 |
mangleQuoted | 不适用 | 不支持 |
metafile | metafile | |
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 | 不适用 | 不支持 |
outExtension | 不适用 | 不支持 |
outbase | root | 名称不同 |
outdir | outdir | 无差异 |
outfile | outfile | 无差异 |
packages | packages | 无差异 |
platform | target | 支持 "bun"、"node" 和 "browser"(默认值)。不支持 "neutral"。 |
plugins | plugins | Bun 的插件 API 是 esbuild 的子集。部分 esbuild 插件无需修改即可与 Bun 配合使用。 |
preserveSymlinks | 不适用 | 不支持 |
publicPath | publicPath | 无差异 |
pure | 不适用 | 不支持 |
reserveProps | 不适用 | 不支持 |
resolveExtensions | 不适用 | 不支持 |
sourceRoot | 不适用 | 不支持 |
sourcemap | sourcemap | 支持 "none"、"linked"、"inline" 和 "external" |
sourcesContent | 不适用 | 不支持 |
splitting | splitting | 无差异 |
stdin | 不适用 | 不支持 |
supported | 不适用 | 不支持 |
target | 不适用 | 不支持语法降级 |
treeShaking | treeShaking | 默认为 true |
tsconfig | tsconfig | |
write | 不适用 | 设置了 outdir/outfile 时为 true,否则为 false |
插件 API
Bun 的插件 API 旨在兼容 esbuild。Bun 不支持 esbuild 的全部插件 API,但实现了核心功能。许多第三方 esbuild 插件无需修改即可与 Bun 配合使用。
在 Bun 和 esbuild 中,插件都通过 builder 对象定义。
import type { BunPlugin } from "bun";
const myPlugin: BunPlugin = {
name: "my-plugin",
setup(builder) {
// 定义插件
},
};
builder 对象的方法可以挂接到打包流程的各个部分。Bun 实现了 onStart、onEnd、onResolve 和 onLoad;但没有实现 esbuild 的钩子 onDispose 和 resolve。Bun 部分实现了 initialOptions:该对象为只读,仅公开 esbuild 选项的一个子集。请改用 config(Bun 的 BuildConfig 格式中具有相同功能的对象)。
import type { BunPlugin } from "bun";
const myPlugin: BunPlugin = {
name: "my-plugin",
setup(builder) {
builder.onStart(() => {
/* 当打包开始时调用 */
});
builder.onResolve(
{
/* onResolve 选项 */
},
args => {
return {
/* onResolve 返回值 */
};
},
);
builder.onLoad(
{
/* onLoad 选项 */
},
args => {
return {
/* onLoad 返回值 */
};
},
);
builder.onEnd(result => {
/* 当打包完成时调用 */
});
},
};
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