Bun
Bun 是一个现代化的 JavaScript 运行时和工具包,由 Jarred Sumner 于 2021 年创建。它不仅是一个高性能的运行时,还内置了包管理器、打包器、测试运行器等工具,旨在成为 Node.js 生态的一站式替代方案。
为什么选择 Bun
Bun 的包管理器是当今最快的 JavaScript 包管理器,相比传统工具有显著优势:
极致性能
Bun 使用 Zig 语言编写,从底层优化了依赖安装过程。在标准基准测试中,Bun 安装依赖的速度比 npm 快 25 倍以上,比 pnpm 和 yarn 快 10 倍以上。这种性能提升源于以下几个方面:
- 使用操作系统最快系统调用:macOS 上使用
clonefile,Linux 上使用hardlink - 全局包缓存:已下载的包存储在全局缓存中,后续安装直接复用
- 并行处理:依赖解析和下载并行进行
- 延迟加载:当
bun.lock存在且package.json未变化时,延迟下载缺失依赖
开箱即用
Bun 不需要额外配置就能在现有 Node.js 项目中工作。只要有 package.json,运行 bun install 即可。它完全兼容 npm 生态系统,支持:
package.json中的所有字段node_modules目录结构- npm、yarn、pnpm 的锁文件格式(可自动迁移)
.npmrc配置文件
安全优先
与 npm 不同,Bun 默认不执行依赖包的生命周期脚本(如 postinstall)。这避免了恶意代码在安装过程中执行的风险。对于需要执行脚本的包,必须显式添加到 trustedDependencies 列表中。
一体化设计
Bun 不仅是一个包管理器,还是一个完整的开发工具链:
- 运行时:替代 Node.js,支持 TypeScript 和 JSX
- 打包器:内置打包功能,无需 webpack 或 esbuild
- 测试运行器:内置测试框架,兼容 Jest API
- 包管理器:替代 npm、yarn、pnpm
安装 Bun
使用安装脚本(推荐)
# macOS 和 Linux
curl -fsSL https://bun.sh/install | bash
# Windows (PowerShell)
powershell -c "irm bun.sh/install.ps1 | iex"
使用包管理器
# 使用 npm 安装
npm install -g bun
# 使用 Homebrew (macOS)
brew install bun
# 使用 Scoop (Windows)
scoop install bun
# 使用 apt (Ubuntu/Debian)
curl -fsSL https://bun.sh/install | bash
使用 Corepack(Node.js 16.10+)
# 启用 Corepack
corepack enable
# 激活 Bun
corepack prepare bun@latest --activate
验证安装
# 查看 Bun 版本
bun --version
# 查看 Bun 安装路径
which bun
# 查看 Bun 帮助
bun --help
升级 Bun
# 升级到最新版本
bun upgrade
# 升级到指定版本
bun upgrade [email protected]
# 升级到 canary 版本
bun upgrade bun@canary
基本使用
初始化项目
# 创建 package.json
bun init
# 交互式初始化
bun init -y
# 创建特定类型的项目
bun init --help
安装依赖
# 安装所有依赖
bun install
# 简写形式
bun
# 安装生产依赖
bun add lodash
# 安装指定版本
bun add [email protected]
# 安装版本范围
bun add lodash@">=4.17.0 <5.0.0"
# 安装最新版本
bun add lodash@latest
安装不同类型的依赖
# 安装开发依赖
bun add -D jest
bun add --dev typescript
# 安装可选依赖
bun add --optional fsevents
# 安装 peer 依赖
bun add --peer react
# 安装精确版本(不使用 ^ 前缀)
bun add --exact lodash
bun add -E lodash
# 全局安装
bun add -g typescript
bun add --global prettier
删除依赖
# 删除依赖
bun remove lodash
# 删除开发依赖
bun remove -D jest
# 删除全局依赖
bun remove -g typescript
更新依赖
# 检查可更新的依赖
bun outdated
# 更新依赖
bun update
# 更新特定包
bun update lodash
# 强制更新(重新从 registry 获取最新版本)
bun update --force
平台特定依赖安装
Bun 支持覆盖原生模块的目标平台,这对于交叉编译或 CI 环境非常有用:
# 覆盖 CPU 架构
bun install --cpu=arm64
bun install --cpu=x64
bun install --cpu=ia32
# 覆盖操作系统
bun install --os=linux
bun install --os=darwin
bun install --os=win32
# 组合使用(例如为 Linux ARM64 安装依赖)
bun install --os=linux --cpu=arm64
可用值:
| 选项 | 接受值 |
|---|---|
--cpu | arm64, x64, ia32, ppc64, s390x |
--os | linux, darwin, win32, freebsd, openbsd, sunos, aix |
Bun 会在锁文件中存储规范的 cpu 和 os 值,跳过当前平台不支持的包。这意味着锁文件在不同平台/架构间保持一致,即使最终安装的包可能不同。
安全功能
最小发布年龄保护
为防止供应链攻击(恶意包快速发布),Bun 支持配置 npm 包的最小发布年龄要求:
# 要求包发布至少 1 小时后才能安装
bun install --min-release-age=3600
# 要求包发布至少 24 小时后才能安装
bun install --min-release-age=86400
或在 bunfig.toml 中配置:
[install]
minimumReleaseAge = 86400 # 24 小时
工作原理:
- 仅影响新包的解析,
bun.lock中已有的包不受影响 - 所有依赖(直接和传递)都会被过滤
- 当版本被年龄限制阻止时,稳定性检查会检测快速 bugfix 模式
- 如果在年龄限制后不久发布了多个版本,会跳过这些可能不稳定的版本
- 精确版本请求(如
[email protected])仍受年龄限制但跳过稳定性检查
可信依赖
Bun 默认不执行依赖包的生命周期脚本,这提高了安全性。对于需要执行脚本的包,必须显式声明:
{
"trustedDependencies": [
"esbuild",
"sharp",
"bcrypt"
]
}
添加可信依赖的快捷方式:
# 安装包并自动添加到 trustedDependencies
bun add --trust my-package
跳过生命周期脚本
# 跳过项目中的生命周期脚本
bun install --ignore-scripts
依赖安装策略
Bun 支持两种依赖安装策略,决定了 node_modules 的组织方式。
提升安装(Hoisted)
这是传统 npm/Yarn 的方式,将所有依赖扁平化到共享的 node_modules 目录:
# 使用提升安装策略
bun install --backend=hardlink
优点:
- 兼容性最好,大多数工具都能正常工作
- 与现有项目无缝迁移
缺点:
- 可能出现"幽灵依赖"问题
- 可以访问未在
package.json中声明的依赖
隔离安装(Isolated)
这是 pnpm 风格的方式,创建严格的依赖隔离:
# 使用隔离安装策略
bun install --backend=symlink
优点:
- 防止幽灵依赖
- 只能访问
package.json中声明的依赖 - 更严格的依赖管理
缺点:
- 某些工具可能不兼容
默认策略
Bun 根据项目类型自动选择默认策略:
- 新建的 monorepo:使用
isolated策略 - 新建的单包项目:使用
hoisted策略 - 现有项目:使用
hoisted策略(保持向后兼容)
锁文件
Bun 使用 bun.lock 作为锁文件格式。从 Bun 1.2 开始,锁文件采用文本格式,便于版本控制和差异比较。
锁文件结构
# bun.lock 示例
lockfileVersion: "1.2"
packages:
[email protected]:
resolution: {integrity: sha512-v3k...}
version: 4.17.21
历史版本
- Bun 1.2 之前:使用二进制格式
bun.lockb - Bun 1.2+:使用文本格式
bun.lock
迁移旧锁文件
# 将旧的二进制锁文件迁移到新格式
bun install --save-text-lockfile --frozen-lockfile --lockfile-only
# 然后删除旧锁文件
rm bun.lockb
CI/CD 环境使用
# 使用冻结锁文件模式
bun install --frozen-lockfile
# 或使用 bun ci 命令
bun ci
工作区(Workspaces)
Bun 原生支持 monorepo 管理,通过 workspaces 字段配置。
配置工作区
{
"name": "my-monorepo",
"private": true,
"workspaces": [
"packages/*",
"apps/*",
"!**/test/**"
]
}
Glob 语法支持:Bun 支持完整的 glob 语法,包括否定模式。
目录结构
my-monorepo/
├── package.json
├── bun.lock
├── packages/
│ ├── core/
│ │ ├── package.json
│ │ └── src/
│ └── utils/
│ ├── package.json
│ └── src/
└── apps/
└── web/
├── package.json
└── src/
workspace 协议
在工作区内引用其他包:
{
"dependencies": {
"@myorg/core": "workspace:*",
"@myorg/utils": "workspace:^"
}
}
| 协议 | 说明 |
|---|---|
workspace:* | 使用精确版本 |
workspace:^ | 使用兼容版本 |
workspace:~ | 使用近似版本 |
过滤安装
在 monorepo 中安装特定包的依赖:
# 安装特定工作区的依赖
bun install --filter @myorg/core
# 安装匹配模式的工作区
bun install --filter "./packages/*"
# 排除特定工作区
bun install --filter "!./apps/web"
运行工作区脚本
# 在特定工作区运行脚本
bun run --filter @myorg/core build
# 在所有工作区运行脚本
bun run --workspaces test
# 并行运行
bun run --workspaces --parallel test
Catalogs(目录)
当多个包需要相同的依赖版本时,Catalogs 允许在根 package.json 中定义一次版本,然后在所有工作区中引用。
配置 Catalogs
{
"catalogs": {
"default": {
"react": "^18.2.0",
"typescript": "^5.0.0",
"jest": "^29.5.0"
},
"react19": {
"react": "^19.0.0",
"react-dom": "^19.0.0"
}
}
}
使用 Catalogs
{
"dependencies": {
"react": "catalog:",
"typescript": "catalog:"
}
}
使用命名 catalog:
{
"dependencies": {
"react": "catalog:react19"
}
}
生命周期脚本
与 npm 的区别
Bun 对生命周期脚本的处理与 npm 有重要区别:
| 行为 | npm | Bun |
|---|---|---|
执行 postinstall | ✓ | ✗(除非在 trustedDependencies) |
执行 preinstall | ✓ | ✓ |
执行 postinstall | ✓ | ✓ |
trustedDependencies
要允许特定包执行生命周期脚本:
{
"trustedDependencies": [
"esbuild",
"sharp",
"my-native-package"
]
}
跳过脚本
# 跳过项目中的生命周期脚本
bun install --ignore-scripts
# 依赖包的生命周期脚本永远不会执行(除非在 trustedDependencies 中)
从其他工具迁移
从 npm 迁移
Bun 完全兼容 package.json 和 package-lock.json:
# 直接运行即可
bun install
# Bun 会自动处理 package-lock.json
从 pnpm 迁移
Bun 可以自动迁移 pnpm 项目:
# Bun 检测到 pnpm-lock.yaml 时会自动迁移
bun install
# 会生成 bun.lock,原 pnpm-lock.yaml 保持不变
迁移时会处理:
- 锁文件格式转换
pnpm-workspace.yaml转换为package.json中的workspacescatalog:协议保留pnpm.overrides转换为overridespnpm.patchedDependencies转换为patchedDependencies
从 yarn 迁移
# Bun 可以读取 yarn.lock
bun install
# 生成 yarn.lock(可选)
bun install --yarn-lock
配置管理
bunfig.toml
Bun 使用 bunfig.toml 进行配置:
# bunfig.toml
[install]
# 设置镜像源
registry = "https://registry.npmmirror.com"
# 生产模式
production = false
# 并发设置
concurrentScripts = 10
concurrentNetwork = 48
# 锁文件设置
saveLockfile = true
frozenLockfile = false
# 生命周期脚本
ignoreScripts = false
# 安装策略
backend = "hardlink" # clonefile, hardlink, symlink, copyfile
[install.lockfile]
# 保存文本格式锁文件
save = true
print = "yarn" # 打印格式
[install.cache]
# 缓存目录
dir = "~/.bun/install/cache"
disable = false
环境变量
| 变量 | 说明 |
|---|---|
BUN_CONFIG_REGISTRY | 设置 npm 镜像源 |
BUN_CONFIG_TOKEN | 设置认证令牌 |
BUN_CONFIG_YARN_LOCKFILE | 保存 yarn.lock |
BUN_CONFIG_SKIP_SAVE_LOCKFILE | 不保存锁文件 |
BUN_CONFIG_SKIP_LOAD_LOCKFILE | 不加载锁文件 |
BUN_CONFIG_SKIP_INSTALL_PACKAGES | 不安装包 |
配置优先级
配置读取优先级从高到低:
- 命令行参数
- 环境变量
- 项目级
bunfig.toml - 用户级
~/.bunfig.toml - 默认值
常用命令速查
| 命令 | 说明 |
|---|---|
bun init | 初始化项目 |
bun install | 安装所有依赖 |
bun | 安装所有依赖(简写) |
bun add <pkg> | 安装依赖 |
bun add -D <pkg> | 安装开发依赖 |
bun add --peer <pkg> | 安装 peer 依赖 |
bun add -g <pkg> | 全局安装 |
bun remove <pkg> | 删除依赖 |
bun update | 更新依赖 |
bun outdated | 检查过期依赖 |
bun run <script> | 运行脚本 |
bun <script> | 运行脚本(简写) |
bun link | 创建本地链接 |
bun unlink | 移除本地链接 |
bun pm cache | 管理缓存 |
bun pm ls | 查看已安装依赖 |
bun pm bin | 查看可执行文件路径 |
bun pm hash | 计算依赖哈希 |
bun pm hash-string | 打印依赖哈希字符串 |
bun pm migrate | 迁移锁文件 |
与其他工具命令对比
| 操作 | npm | pnpm | yarn | Bun |
|---|---|---|---|---|
| 安装依赖 | npm install | pnpm install | yarn | bun install |
| 添加依赖 | npm install <pkg> | pnpm add <pkg> | yarn add <pkg> | bun add <pkg> |
| 添加开发依赖 | npm install -D <pkg> | pnpm add -D <pkg> | yarn add -D <pkg> | bun add -D <pkg> |
| 全局安装 | npm install -g <pkg> | pnpm add -g <pkg> | yarn global add <pkg> | bun add -g <pkg> |
| 删除依赖 | npm uninstall <pkg> | pnpm remove <pkg> | yarn remove <pkg> | bun remove <pkg> |
| 更新依赖 | npm update | pnpm update | yarn upgrade | bun update |
| 运行脚本 | npm run <script> | pnpm run <script> | yarn <script> | bun <script> |
| 执行包命令 | npx <cmd> | pnpm dlx <cmd> | yarn dlx <cmd> | bunx <cmd> |
| CI 安装 | npm ci | pnpm install --frozen-lockfile | yarn install --immutable | bun install --frozen-lockfile |
最佳实践
1. 使用冻结锁文件
在 CI/CD 环境中,始终使用冻结锁文件模式:
# .github/workflows/ci.yml
- name: Install dependencies
run: bun install --frozen-lockfile
2. 配置 trustedDependencies
只信任必要的包:
{
"trustedDependencies": [
"esbuild",
"sharp"
]
}
3. 使用 Catalogs 管理版本
在 monorepo 中统一管理依赖版本:
{
"catalogs": {
"default": {
"react": "^18.2.0",
"typescript": "^5.0.0"
}
}
}
4. 选择合适的安装策略
- 新项目:使用默认策略即可
- 严格依赖管理:使用
--backend=symlink隔离模式 - 兼容性要求高:使用
--backend=hardlink提升模式
5. 配置镜像源
在国内使用镜像源加速:
# bunfig.toml
[install]
registry = "https://registry.npmmirror.com"
或使用环境变量:
BUN_CONFIG_REGISTRY=https://registry.npmmirror.com bun install
6. 安全审计
# Bun 会自动跳过可疑的生命周期脚本
# 检查已信任的依赖
bun pm ls
性能对比
以下是在相同环境下安装一个中型项目的依赖所需时间:
| 工具 | 首次安装 | 有缓存 |
|---|---|---|
| npm | ~30s | ~10s |
| pnpm | ~15s | ~5s |
| yarn | ~20s | ~5s |
| Bun | ~1s | ~0.5s |
Bun 的速度优势主要来自:
- 全局缓存:已下载的包直接复用
- 系统调用优化:使用操作系统最快的文件操作
- 并行处理:依赖解析和下载并行进行
- 懒加载:只在需要时下载缺失依赖
了解更多
- Bun 官网:https://bun.sh
- Bun 文档:https://bun.sh/docs
- Bun GitHub:https://github.com/oven-sh/bun
- Bun Discord:https://bun.sh/discord