运行时包管理器打包器测试运行器代码检查格式化指南参考博客反馈

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。

esbuildbun build备注
--bundle不适用Bun 始终会进行打包;使用 --no-bundle 禁用打包。
--define:K=V--define K=V语法略有不同;没有冒号。
esbuild --define:foo=bar
bun build --define foo=bar
--external:<pkg>--external <pkg>语法略有不同;没有冒号。
esbuild --external:react
bun build --external react
--format--formatBun 支持 "esm"、"cjs" 和 "iife"。esbuild 默认为 "iife"。
--loader:.ext=loader--loader .ext:loaderBun 支持的内置加载器与 esbuild 不同;请参阅 加载器。esbuild 的加载器 dataurl、binary、base64、copy 和 empty 尚未实现。

--loader 的语法有所不同。
esbuild app.ts --bundle --loader:.svg=text
bun 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
不适用--featureBun 特有。通过 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
assetNamesnaming.asset使用与 esbuild 相同的模板语法,但必须明确包含 [ext]。

ts<br/>Bun.build({<br/> entrypoints: ["./index.tsx"],<br/> naming: {<br/> asset: "[name].[ext]",<br/> },<br/>});<br/>
bannerbanner仅适用于 JS 包
bundle不适用始终为 true。使用 Bun.Transpiler 可在不打包的情况下进行转译。
charset不适用不支持
chunkNamesnaming.chunk使用与 esbuild 相同的模板语法,但必须明确包含 [ext]。

ts<br/>Bun.build({<br/> entrypoints: ["./index.tsx"],<br/> naming: {<br/> chunk: "[name].[ext]",<br/> },<br/>});<br/>
color不适用Bun 会在构建结果的 logs 属性中返回日志。
conditionsconditions无差异
definedefine
dropdrop
entryNamesnaming 或 naming.entryBun 支持 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/>
entryPointsentrypoints大小写不同
externalexternal无差异
footerfooter仅适用于 JS 包
formatformat支持 "esm"、"cjs" 和 "iife"。
globalName不适用不支持
ignoreAnnotationsignoreDCEAnnotations
inject不适用不支持
jsxjsx.runtime支持 "automatic" 和 "classic"
jsxDevjsx.development
jsxFactoryjsx.factory
jsxFragmentjsx.fragment
jsxImportSourcejsx.importSource
jsxSideEffectsjsx.sideEffects
keepNamesminify.keepNames
legalComments不适用不支持
loaderloaderBun 支持的内置加载器与 esbuild 不同;请参阅 加载器。Bun 尚未实现 esbuild 的加载器 dataurl、binary、base64、copy 和 empty。
logLevel不适用不支持
logLimit不适用不支持
logOverride不适用不支持
mainFields不适用不支持
mangleCache不适用不支持
mangleProps不适用不支持
mangleQuoted不适用不支持
metafilemetafile
minifyminify在 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/>
minifyIdentifiersminify.identifiers请参阅 minify
minifySyntaxminify.syntax请参阅 minify
minifyWhitespaceminify.whitespace请参阅 minify
nodePaths不适用不支持
outExtension不适用不支持
outbaseroot名称不同
outdiroutdir无差异
outfileoutfile无差异
packagespackages无差异
platformtarget支持 "bun"、"node" 和 "browser"(默认值)。不支持 "neutral"。
pluginspluginsBun 的插件 API 是 esbuild 的子集。部分 esbuild 插件无需修改即可与 Bun 配合使用。
preserveSymlinks不适用不支持
publicPathpublicPath无差异
pure不适用不支持
reserveProps不适用不支持
resolveExtensions不适用不支持
sourceRoot不适用不支持
sourcemapsourcemap支持 "none"、"linked"、"inline" 和 "external"
sourcesContent不适用不支持
splittingsplitting无差异
stdin不适用不支持
supported不适用不支持
target不适用不支持语法降级
treeShakingtreeShaking默认为 true
tsconfigtsconfig
write不适用设置了 outdir/outfile 时为 true,否则为 false

插件 API

Bun 的插件 API 旨在兼容 esbuild。Bun 不支持 esbuild 的全部插件 API,但实现了核心功能。许多第三方 esbuild 插件无需修改即可与 Bun 配合使用。

在 Bun 和 esbuild 中,插件都通过 builder 对象定义。

myPlugin.ts
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 格式中具有相同功能的对象)。

myPlugin.ts
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

onLoad

  • 🟢 filter
  • 🟢 namespace