Skip to main content
使用 Bun 的原生打包器,通过 bun build CLI 命令或 Bun.build() JavaScript API。

一览

  • JS API:await Bun.build({ entrypoints, outdir })
  • CLI:bun build <entry> --outdir ./out
  • 监视模式:--watch 用于增量重新构建
  • 目标:--target browser|bun|node
  • 格式:--format esm|cjs|iife(cjs/iife 为实验性)
build.ts
它很快。以下数据来自 esbuild 的 three.js 基准测试

为什么要打包?

打包器解决了几个问题:
  • 减少 HTTP 请求。 node_modules 中的单个包可能包含数百个文件,大型应用可能有几十个这样的依赖。用单独的 HTTP 请求加载每个文件是不可行的,因此打包器将你的应用源代码转换为数量更少的自包含”包”,可以通过单个请求加载。
  • 代码转换。 现代应用通常使用 TypeScript、JSX 和 CSS 模块等语言或工具构建,所有这些在浏览器消费之前必须转换为普通 JavaScript 和 CSS。打包器是配置这些转换的自然位置。
  • 框架功能。 框架依赖打包器插件和代码转换来实现常见模式,如文件系统路由、客户端-服务器代码共置(比如 getServerSideProps 或 Remix loader)以及服务器组件。
  • 全栈应用。 Bun 的打包器可以在单个命令中处理服务器和客户端代码,实现优化后的生产构建和单文件可执行文件。通过构建时的 HTML 导入,你可以将整个应用程序(前端资源和后端服务器)打包到一个可部署的单元中。
Bun 打包器不打算替代 tsc 进行类型检查或生成类型声明。

基本示例

构建你的第一个包。你有以下两个文件,实现了一个客户端渲染的 React 应用。
这里,index.tsx 是应用的”入口点”:打包器开始的文件。通常这是一个执行某些副作用的脚本,比如启动服务器,或者在本例中初始化 React 根节点。因为这些文件使用了 TypeScript 和 JSX,代码必须先打包才能发送到浏览器。 要创建包:
对于 entrypoints 中指定的每个文件,Bun 生成一个新的包并将其写入 ./out 目录(从当前工作目录解析)。运行构建后,文件系统看起来像这样:
file system
out/index.js 的内容看起来像这样:
out/index.js

监视模式

与运行时和测试运行器一样,打包器原生支持监视模式。
terminal

内容类型

与 Bun 运行时一样,打包器默认支持一系列文件类型。下表列出了打包器的标准”加载器”。请参见加载器

资源

如果打包器遇到无法识别的扩展名的导入,它会将导入的文件视为外部文件。引用的文件被原样复制到 outdir 中,导入被解析为文件的路径。
文件加载器的确切行为还取决于 namingpublicPath
关于文件加载器的更多信息,请参见加载器

插件

插件可以覆盖或扩展此表中描述的行为。请参见加载器

API

entrypoints

必需 对应应用入口点的路径数组。Bun 为每个入口点生成一个包。
build.ts

files

一个文件路径到文件内容的映射,用于内存中打包:打包磁盘上不存在的虚拟文件,或覆盖确实存在的文件内容。此选项仅在 JavaScript API 中可用。 文件内容可以作为 stringBlobTypedArrayArrayBuffer 提供。

完全从内存中打包

你可以在没有任何磁盘文件的情况下打包代码,方法是在 files 中提供所有源代码:
build.ts
当所有入口点都在 files 映射中时,当前工作目录被用作根目录。

覆盖磁盘上的文件

内存中的文件优先于磁盘上的文件,因此你可以在保持代码库其余部分不变的同时覆盖特定文件:
build.ts

混合磁盘和虚拟文件

磁盘上的真实文件可以导入虚拟文件,虚拟文件也可以导入真实文件:
build.ts
用于代码生成、注入构建时常量或使用模拟模块进行测试。

outdir

输出文件写入的目录。
build.ts
如果 JavaScript API 没有传入 outdir,打包后的代码不会写入磁盘。打包后的文件以 BuildArtifact 对象数组的形式返回。这些对象是带有额外属性的 Blob;请参见输出
build.ts
当设置了 outdir 时,BuildArtifact 上的 path 属性是其写入的绝对路径。

target

打包产物的预期执行环境。
build.ts
根据目标的不同,Bun 会应用不同的模块解析规则和优化。

browser

默认。 适用于在浏览器中运行的包。解析导入时优先考虑 "browser" 导出条件。 导入内置模块如 node:eventsnode:path 可以工作,但调用某些函数,如 fs.readFile, 则不行。

bun

适用于在 Bun 运行时中运行的包。在许多情况下,没有必要打包服务器端代码;你可以直接执行源代码而无需修改。然而,打包你的服务器代码可以减少启动时间并提高运行性能。将此目标用于具有构建时 HTML 导入的全栈应用,其中服务器和客户端代码被打包在一起。所有以 target: "bun" 生成的包都带有 // @bun 编译指示,这告诉 Bun 运行时在执 行前无需重新转译文件。如果任何入口点包含 Bun shebang(#!/usr/bin/env bun),打包器默认使用 target: "bun" 而不是 "browser"当同时使用 target: "bun"format: "cjs" 时,会添加 // @bun @bun-cjs 编译指示,并且 CommonJS 包装函数与 Node.js 不兼容。

node

适用于在 Node.js 中运行的包。解析导入时优先考虑 "node" 导出条件。Bun 不会 polyfill Bun 全局变量或内置的 bun:* 模块。

format

指定生成打包产物的模块格式。 Bun 默认使用 "esm",并提供了对 "cjs""iife" 的实验性支持。

format: “esm” - ES Module

默认格式。支持 ES Module 语法,包括顶层 await 和 import.meta
build.ts
要在浏览器中使用 ES Module 语法,将 format 设置为 "esm",并使用 <script type="module"> 标签加载包。

format: “cjs” - CommonJS

要构建 CommonJS 模块,将 format 设置为 "cjs"。选择 "cjs" 时,默认目标从 "browser"(esm)变为 "node"(cjs)。使用 format: "cjs"target: "node" 转译的 CommonJS 模块在 Bun 和 Node.js 中都运行(假设使用的 API 两者都支持)。
build.ts

format: “iife” - IIFE

TODO:在支持 globalNames 后记录 IIFE。

jsx

配置 JSX 的编译方式。 经典运行时示例(使用 factoryfragment):
自动运行时示例(使用 importSource):

splitting

是否启用代码分割。
build.ts
当为 true 时,打包器启用代码分割。当多个入口点导入相同的文件或模块时,打包器可以将共享代码分割为单独的包,称为。考虑以下文件:
要打包启用了代码分割的 entry-a.tsentry-b.ts
build.ts
运行此构建会生成以下文件:
file system
生成的 chunk-2fce6291bf86559d.js 文件包含共享代码。为避免冲突,文件名默认包含内容哈希。使用 naming 自定义。

plugins

在打包期间使用的插件列表。
build.ts
Bun 的插件系统由运行时和打包器共享。请参见插件

env

控制打包期间环境变量的处理方式。内部使用 define 将环境变量注入打包产物;env 是指定哪些变量的简写。

env: “inline”

通过将 process.env.FOO 引用转换为包含实际环境变量值的字符串字面量,将环境变量注入打包输出。
build.ts
对于以下输入:
input.js
生成的包包含以下代码:
output.js

env: “PUBLIC_*“(前缀)

内联匹配给定前缀(* 字符之前的部分)的环境变量,将 process.env.FOO 替换为实际的环境变量值。使用前缀可只内联公共值,如面向外部的 URL 或客户端令牌,而无需将私有凭据注入输出包中。
build.ts
例如,给定以下环境变量:
terminal
以及源代码:
index.tsx
生成的包包含以下代码:
output.js

env: “disable”

完全禁用环境变量注入。

sourcemap

指定生成的 sourcemap 类型。
build.ts
相关的 *.js.map sourcemap 是一个 JSON 文件,包含等效的 debugId 属性。

minify

是否启用压缩。默认为 false 要启用所有压缩选项:
build.ts
要精细启用某些压缩:
build.ts

external

要视为外部的导入路径列表。默认为 []
build.ts
外部导入不会包含在最终包中。相反,导入语句原样保留,在运行时解析。 例如,考虑以下入口点文件:
index.tsx
通常,打包 index.tsx 会生成包含 “zod” 包完整源代码的包。要原样保留导入语句,将其标记为外部:
build.ts
生成的包看起来像这样:
out/index.js
要将所有导入标记为外部,使用通配符 *
build.ts

packages

控制是否在包中包含包依赖项。可能的值:bundle(默认)、external。Bun 将任何路径不以 .../ 开头的导入视为包。
build.ts

naming

自定义生成的文件名。默认为 ./[dir]/[name].[ext]
build.ts
默认情况下,生成的包名称基于关联入口点的名称。
file system
对于多个入口点,生成的文件层次结构反映入口点的目录结构。
file system
naming 字段自定义生成文件的名称和位置。它接受一个模板字符串,用于所有对应入口点的包,其中以下令牌被替换为其值:
  • [name] - 入口点文件的名称,不带扩展名。
  • [ext] - 生成包的扩展名。
  • [hash] - 包内容的哈希值。
  • [dir] - 从项目根目录到源文件父目录的相对路径。
例如: 组合这些令牌以创建模板字符串。例如,在生成的包名称中包含哈希:
build.ts
此构建将产生以下文件结构:
file system
当为 naming 字段提供字符串时,仅用于对应入口点的包。块和复制资源的名称不受影响。在 JavaScript API 中,你可以为每种类型的生成文件指定单独的模板字符串。
build.ts

root

项目的根目录。
build.ts
如果未指定,它会计算为所有入口点文件的第一个公共祖先。考虑以下文件结构:
file system
构建 pages 目录中的两个入口点:
这将产生如下文件结构:
file system
由于 pages 目录是入口点文件的第一个公共祖先,它被视为项目根目录,因此生成的包位于 out 目录的顶层;没有 out/pages 目录。 通过指定 root 选项覆盖此行为:
.root,生成的文件结构如下:

publicPath

添加到打包代码中任何导入路径的前缀。 在许多情况下,生成的包不包含导入语句;打包的目标是将所有代码合并到一个文件中。然而,在少数情况下,生成的包确实包含导入语句:
  • 资源导入 — 当导入无法识别的文件类型如 *.svg 时,打包器委托文件加载器处理,该加载器将文件原样复制到 outdir 中。导入被转换为变量。
  • 外部模块 — 标记为外部的文件和模块不会包含在包中。相反,导入语句保留在最终包中。
  • 分块。当启用 splitting 时,打包器可能会生成代表多个入口点间共享代码的单独”块”文件。
在任何这些情况下,最终包可能包含指向其他文件的路径。默认情况下,这些导入是相对的。以下是一个资源导入的示例:
设置 publicPath 会为所有文件路径添加指定值作为前缀。
build.ts
输出文件现在看起来像这样:
out/index.js

define

要在构建时替换的全局标识符映射。此对象的键是标识符名称,值是内联的 JSON 字符串。
build.ts

loader

文件扩展到内置加载器名称的映射。用于自定义某些文件的加载方式。
build.ts
添加到最终包的 banner。可以是像 React 的 "use client" 这样的指令,或像许可证这样的注释块。
build.ts
添加到最终包的 footer。可以是许可证的注释块或有趣的彩蛋。
build.ts

drop

从包中移除函数调用。例如,--drop=console 移除对 console.log 的所有调用。被丢弃调用的参数也会被移除,即使它们有副作用。丢弃 debugger 会移除所有 debugger 语句。
build.ts

features

为死代码消除启用编译时特性标志:使用 import { feature } from "bun:bundle" 在打包时有条件地包含或排除代码路径。
app.ts
build.ts
feature() 函数在打包时被替换为 truefalse。结合压缩,不可达代码被消除:
输入
输出(带 --feature PREMIUM --minify)
输出(不带 --feature PREMIUM,带 --minify)
关键行为:
  • feature() 需要字符串字面量参数——不支持动态值
  • bun:bundle 导入完全从输出中移除
  • 适用于 bun buildbun runbun test
  • 多个标志可以同时启用:--feature FLAG_A --feature FLAG_B
  • 对于类型安全,扩展 Registry 接口以将 feature() 限制为已知标志
用例:
  • 平台特定代码(feature("SERVER") vs feature("CLIENT")
  • 基于环境的功能(feature("DEVELOPMENT")
  • 渐进式功能发布
  • A/B 测试变体
  • 付费层级功能
类型安全: 默认情况下,feature() 接受任何字符串。要获得自动补全并在编译时捕获拼写错误,创建一个 env.d.ts 文件(或添加到现有的 .d.ts)并扩展 Registry 接口:
env.d.ts
确保该文件包含在你的 tsconfig.json 中(例如,"include": ["src", "env.d.ts"])。现在 feature() 只接受这些标志,像 feature("TYPO") 这样的无效字符串会变成类型错误。

optimizeImports

跳过对 barrel 文件(重新导出的索引文件)中未使用子模块的解析。当你从大型库中只导入少量命名导出时,通常打包器会解析 barrel 重新导出的每个文件。使用 optimizeImports,只解析你使用的子模块。
build.ts
例如,import { Button } from 'antd' 通常会解析 antd/index.js 重新导出的所有约 3000 个模块。使用 optimizeImports: ['antd'],只解析 Button 子模块。 这适用于纯 barrel 文件——每个命名导出都是重新导出的文件(export { X } from './x')。如果 barrel 文件有任何本地导出(export const foo = ...),或者任何导入者使用 import *,所有子模块都会被加载。 export * 重新导出总是被加载(从不延迟)以避免循环解析问题。只有不被任何导入者使用的命名重新导出(export { X } from './x')会被延迟。 自动模式:package.json 中带有 "sideEffects": false 的包会自动获得 barrel 优化——无需配置 optimizeImports。对于没有此字段的包,使用 optimizeImports 插件: Resolve 和 load 插件与 barrel 优化一起工作。延迟的子模块在最终加载时会经过插件流水线。

metafile

以结构化格式生成关于构建的元数据。元数据描述每个输入和输出文件:大小、导入和导出。用于:
  • 包分析:了解哪些内容对包体积有贡献
  • 可视化:输入到 esbuild 的包分析器等工具
  • 依赖跟踪:查看应用程序的完整导入图
  • CI 集成:跟踪包体积随时间的变化
build.ts

Markdown 元数据文件

使用 --metafile-md 生成 markdown 格式的元数据文件,对 LLM 友好,终端可读:
terminal
--metafile--metafile-md 可以同时使用:
terminal

metafile 选项格式

在 JavaScript API 中,metafile 接受多种形式:
build.ts
元数据结构包含:

输出

Bun.build 函数返回一个 Promise<BuildOutput>,定义如下:
build.ts
outputs 数组包含构建生成的所有文件。每个 artifact 都实现了 Blob 接口。
build.ts
每个 artifact 还包含以下属性: BunFile 类似,BuildArtifact 对象可以直接传递给 new Response()
build.ts
Bun 运行时漂亮地打印 BuildArtifact 对象以简化调试。

字节码

bytecode: boolean 选项为任何 JavaScript/TypeScript 入口点生成字节码,这可以大大改善大型应用的启动时间。需要 "target": "bun" 和匹配的 Bun 版本。
  • CommonJS:可以使用或不使用 compile: true。在每个入口点旁边生成一个 .jsc 文件。
  • ESM:需要 compile: true。字节码和模块元数据嵌入到独立可执行文件中。
没有显式的 format 时,字节码默认为 CommonJS。
build.ts

可执行文件

Bun 支持将 JavaScript/TypeScript 入口点”编译”为独立可执行文件。此可执行文件包含一份 Bun 二进制文件的副本。
terminal
请参见独立可执行文件

日志和错误

失败时,Bun.build 返回一个带有 AggregateError 的 rejected promise。将其记录到控制台以漂亮打印错误列表,或使用 try/catch 块以编程方式读取。
build.ts
大多数时候,不需要显式的 try/catch,因为 Bun 会打印未捕获的异常。你可以在 Bun.build 调用上使用顶层 await。 error.errors 中的每个项都是 BuildMessageResolveMessageError 的子类)的实例,包含每个错误的详细信息。
build.ts
构建成功时,返回的对象包含一个 logs 属性,其中包含打包器的警告和信息消息。
build.ts

参考

TypeScript 定义

CLI 用法

通用配置

--production
boolean
设置 NODE_ENV=production 并启用压缩
--bytecode
boolean
编译时使用字节码缓存
--target
string
default:"browser"
打包的预期执行环境。可选:browserbunnode
--conditions
string
传递自定义解析条件
--env
string
default:"disable"
将环境变量内联到打包文件中,作为 process.env.$。要内联匹配前缀的变量,使用类似 FOO_PUBLIC_* 的 glob

输出与文件处理

--outdir
string
default:"dist"
输出目录(构建多个入口点时使用)
--outfile
string
将输出写入特定文件
--sourcemap
string
default:"none"
生成 source map。可选:linkedinlineexternalnone
--banner
string
在输出中添加横幅(例如 React Server Components 的 “use client”
在输出中添加页脚(例如 // built with bun!
--format
string
default:"esm"
输出包的模块格式。可选:esmcjsiife。使用 —bytecode 时默认为 cjs

文件命名

--entry-naming
string
default:"[dir]/[name].[ext]"
自定义入口点文件名
--chunk-naming
string
default:"[name]-[hash].[ext]"
自定义代码块文件名
--asset-naming
string
default:"[name]-[hash].[ext]"
自定义资源文件名

打包选项

--root
string
打包多个入口点时使用的根目录
--splitting
boolean
为共享模块启用代码分割
--public-path
string
添加到打包代码中导入路径的前缀
--external
string
从打包中排除模块(支持通配符)。别名:-e
--packages
string
default:"bundle"
如何处理依赖:externalbundle
--no-bundle
boolean
仅转译——不打包
--css-chunking
boolean
将 CSS 文件合并打包以减少重复(仅在多个入口点导入 CSS 时)

压缩与优化

--emit-dce-annotations
boolean
default:"true"
重新发出死代码消除注解。使用 —minify-whitespace 时禁用
--minify
boolean
启用所有压缩选项
--minify-syntax
boolean
压缩语法和内联常量
--minify-whitespace
boolean
压缩空白
--minify-identifiers
boolean
压缩变量和函数标识符
--keep-names
boolean
压缩时保留原始函数和类名

开发功能

--watch
boolean
文件变化时自动重新构建
--no-clear-screen
boolean
使用 —watch 重新构建时不清除终端屏幕
--react-fast-refresh
boolean
启用 React Fast Refresh 转换(用于开发测试)
--react-compiler
boolean
.jsx/.tsx 文件上运行 React Compiler,自动记忆组件和钩子。输出模式由 —target 决定(browser → 客户端,bun/node → ssr)。实验性功能。

独立可执行文件

--compile
boolean
生成包含打包文件的独立 Bun 可执行文件
--compile-exec-argv
string
将参数预先附加到独立可执行文件的 execArgv

Windows 可执行文件详情

--windows-hide-console
boolean
运行编译后的 Windows 可执行文件时阻止控制台窗口打开
--windows-icon
string
设置 Windows 可执行文件的图标
--windows-title
string
设置 Windows 可执行文件的产品名称
--windows-publisher
string
设置 Windows 可执行文件的公司名称
--windows-version
string
设置 Windows 可执行文件的版本(例如 1.2.3.4
--windows-description
string
设置 Windows 可执行文件的描述
设置 Windows 可执行文件的版权声明

实验性与应用构建

--app
boolean
(实验性)使用 Bun Bake 构建生产版 Web 应用
--server-components
boolean
(实验性)启用 React Server Components
--debug-dump-server-files
boolean
当设置了 —app 时,即使在静态构建中也将所有服务端文件转储到磁盘
--debug-no-minify
boolean
当设置了 —app 时,禁用所有压缩