Appearance
可执行文件
Bun 可执行文件生成指南
Bun 提供了强大的打包工具,可以将 TypeScript 或 JavaScript 文件编译成独立的可执行文件。这一功能通过 --compile
标志实现,让开发者能够轻松创建跨平台的应用程序。
基本使用
INFO
什么是可执行文件?可执行文件是一种无需解释器直接运行的二进制文件。对于 Bun 项目,这意味着用户无需安装 Bun 即可运行您的应用程序。
要创建一个简单的可执行文件,使用以下命令:
bash
bun build ./cli.ts --compile --outfile mycli
ts
console.log("Hello world!");
生成的可执行文件可以直接执行:
bash
$ ./mycli
Hello world!
Bun 会将所有导入的文件和包,以及 Bun 运行时捆绑到可执行文件中。所有内置的 Bun 和 Node.js API 都受支持。
跨平台编译
使用 --target
标志可以为不同的操作系统、架构或 Bun 版本编译可执行文件。这使您能在一台机器上为多种目标平台构建应用。
为 Linux x64 平台构建
bash
# 基本构建
bun build --compile --target=bun-linux-x64 ./index.ts --outfile myapp
# 支持2013年前的CPU (baseline版本,兼容性更好)
bun build --compile --target=bun-linux-x64-baseline ./index.ts --outfile myapp
# 仅支持2013年及之后的CPU (modern版本,性能更好)
bun build --compile --target=bun-linux-x64-modern ./index.ts --outfile myapp
为 Linux ARM64 平台构建
bash
# 适用于Graviton或Raspberry Pi等设备
bun build --compile --target=bun-linux-arm64 ./index.ts --outfile myapp
为 Windows 平台构建
bash
# 基本构建
bun build --compile --target=bun-windows-x64 ./path/to/my/app.ts --outfile myapp
# 支持2013年前的CPU (baseline版本)
bun build --compile --target=bun-windows-x64-baseline ./path/to/my/app.ts --outfile myapp
# 仅支持2013年及之后的CPU (modern版本)
bun build --compile --target=bun-windows-x64-modern ./path/to/my/app.ts --outfile myapp
对于 Windows 可执行文件,如果没有提供`.exe`扩展名,Bun 会自动添加。
为 macOS 平台构建
bash
# ARM64架构(例如M系列芯片)
bun build --compile --target=bun-darwin-arm64 ./path/to/my/app.ts --outfile myapp
# x64架构(Intel芯片)
bun build --compile --target=bun-darwin-x64 ./path/to/my/app.ts --outfile myapp
支持的目标平台
下表展示了所有受支持的目标平台配置:
目标平台 | 操作系统 | 架构 | Modern 支持 | Baseline 支持 | Libc |
---|---|---|---|---|---|
bun-linux-x64 | Linux | x64 | ✅ | ✅ | glibc |
bun-linux-arm64 | Linux | arm64 | ✅ | N/A | glibc |
bun-windows-x64 | Windows | x64 | ✅ | ✅ | - |
Windows | arm64 | ❌ | ❌ | - | |
bun-darwin-x64 | macOS | x64 | ✅ | ✅ | - |
bun-darwin-arm64 | macOS | arm64 | ✅ | N/A | - |
bun-linux-x64-musl | Linux | x64 | ✅ | ✅ | musl |
bun-linux-arm64-musl | Linux | arm64 | ✅ | N/A | musl |
对于 x64 平台,Bun 利用 SIMD 优化来提升性能,这需要支持 AVX2 指令集的现代 CPU。如果目标设备较旧,应使用`-baseline`版本。如果您或用户遇到"Illegal instruction"错误,很可能需要使用 baseline 版本。
部署到生产环境
编译后的可执行文件有助于减少内存使用并改善 Bun 的启动时间。通常,Bun 会在import
和require
时读取并转译 JavaScript 和 TypeScript 文件。这使得 Bun"开箱即用",但会消耗时间和内存。
使用编译后的可执行文件,您可以将这些成本从运行时转移到构建时。
生产环境部署推荐命令:
bash
bun build --compile --minify --sourcemap ./path/to/my/app.ts --outfile myapp
字节码编译
要进一步提高启动时间,可以启用字节码编译:
bash
bun build --compile --minify --sourcemap --bytecode ./path/to/my/app.ts --outfile myapp
使用字节码编译,应用程序如tsc
的启动速度可提高 2 倍:
字节码编译是 Bun v1.1.30 引入的实验性功能,目前仅支持`cjs`格式(意味着不支持顶层 await)。
参数详解
--minify
: 优化转译输出代码的大小。对于大型应用,可以节省兆字节级空间。--sourcemap
: 嵌入用 zstd 压缩的源映射,使错误和堆栈跟踪指向原始位置。--bytecode
: 启用字节码编译,将源代码解析工作从运行时转移到构建时,节省启动时间。
Worker 支持
要在独立可执行文件中使用工作线程,需要将 worker 的入口点添加到 CLI 参数中:
bash
bun build --compile ./index.ts ./my-worker.ts --outfile myapp
然后在代码中引用 worker:
ts
console.log("Hello from Bun!");
// 以下任何一种方式都有效:
new Worker("./my-worker.ts");
new Worker(new URL("./my-worker.ts", import.meta.url));
new Worker(new URL("./my-worker.ts", import.meta.url).href);
从 Bun v1.1.25 开始,添加到可执行文件的多个入口点将被分别打包。如果使用相对路径引用未包含在可执行文件中的文件,Bun 会尝试从进程的当前工作目录相对加载该路径。
SQLite 支持
bun build --compile
支持bun:sqlite
导入。默认情况下,数据库相对于进程的当前工作目录进行解析。
js
import db from "./my.db" with { type: "sqlite" };
console.log(db.query("select * from users LIMIT 1").get());
示例:如果可执行文件位于/usr/bin/hello
,用户终端位于/home/me/Desktop
,它将查找/home/me/Desktop/my.db
。
bash
$ cd /home/me/Desktop
$ ./hello
嵌入资源和文件
基本文件嵌入
独立可执行文件支持嵌入文件。要在可执行文件中嵌入文件,只需在代码中导入:
ts
// 这会成为一个内部文件路径
import icon from "./icon.png" with { type: "file" };
import { file } from "bun";
export default {
fetch(req) {
// 嵌入文件可以从Response对象中流式传输
return new Response(file(icon));
},
};
嵌入文件可以使用Bun.file
函数或 Node.js 的fs.readFile
函数读取:
js
import icon from "./icon.png" with { type: "file" };
import { file } from "bun";
const bytes = await file(icon).arrayBuffer();
// 或使用: await fs.promises.readFile(icon)
// 或使用: fs.readFileSync(icon)
嵌入 SQLite 数据库
如果应用程序需要嵌入 SQLite 数据库,在导入属性中设置type: "sqlite"
和embed: "true"
:
js
import myEmbeddedDb from "./my.db" with { type: "sqlite", embed: "true" };
console.log(myEmbeddedDb.query("select * from users LIMIT 1").get());
嵌入的数据库支持读写,但所有更改在可执行文件退出后都会丢失(因为它存储在内存中)。
嵌入 N-API 附加组件
自 Bun v1.0.23 起,可以将.node
文件嵌入到可执行文件中:
js
const addon = require("./addon.node");
console.log(addon.hello());
如果使用`@mapbox/node-pre-gyp`或类似工具,需确保直接 require `.node`文件,否则打包可能不正确。
嵌入目录
要嵌入目录,在bun build
命令中使用 shell 通配符:
bash
bun build --compile ./index.ts ./public/**/*.png
然后在代码中引用文件:
ts
import icon from "./public/assets/icon.png" with { type: "file" };
import { file } from "bun";
export default {
fetch(req) {
return new Response(file(icon));
},
};
列出嵌入文件
要获取所有嵌入文件的列表,使用Bun.embeddedFiles
:
js
import "./icon.png" with { type: "file" };
import { embeddedFiles } from "bun";
console.log(embeddedFiles[0].name); // `icon-${hash}.png`
Bun.embeddedFiles
返回一个Blob
对象数组,可用于获取文件的大小、内容和其他属性:
ts
embeddedFiles: Blob[]
嵌入文件列表不包括打包的源代码,如`.ts`和`.js`文件。
内容哈希
默认情况下,嵌入文件的名称会附加内容哈希值。这在提供文件 URL 服务或 CDN 时很有用,可减少缓存失效问题。如需禁用内容哈希,使用--asset-naming
参数:
bash
bun build --compile --asset-naming="[name].[ext]" ./index.ts
代码压缩
要稍微减小可执行文件的大小,向bun build --compile
传递--minify
参数。这使用 Bun 的压缩器减少代码大小。
Windows 特定标志
在 Windows 上编译独立可执行文件时,有两个平台特定选项可用于自定义生成的.exe
文件元数据:
--windows-icon=path/to/icon.ico
:自定义可执行文件图标。--windows-hide-console
:禁用背景终端,适用于不需要 TTY 的应用程序。
WARNING
这些标志目前不能用于跨平台编译,因为它们依赖于 Windows API。
macOS 代码签名
要在 macOS 上为独立可执行文件进行代码签名(修复 Gatekeeper 警告),使用codesign
命令:
bash
codesign --deep --force -vvvv --sign "XXXXXXXXXX" ./myapp
建议包含具有 JIT 权限的entitlements.plist
文件:
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>
要使用 JIT 支持进行代码签名,向codesign
传递--entitlements
标志:
bash
codesign --deep --force -vvvv --sign "XXXXXXXXXX" --entitlements entitlements.plist ./myapp
代码签名后,验证可执行文件:
bash
codesign -vvv --verify ./myapp
./myapp: valid on disk
./myapp: satisfies its Designated Requirement
TIP
代码签名支持需要 Bun v1.2.4 或更新版本。
不支持的 CLI 参数
目前,--compile
标志每次只能接受一个入口点,且不支持以下标志:
--outdir
— 请使用outfile
代替--splitting
--public-path
--target=node
或--target=browser
--format
- 始终输出二进制可执行文件(内部几乎是 esm)--no-bundle
- 始终将所有内容打包到可执行文件中