pnpm vs bun install 对比

内容寻址存储(content-addressable store)、严格隔离、成熟的供应链审查

VS
bun install

Rust 内核、速度快、作为 Bun runtime 一体化工具链一部分的安装组件

16 分钟阅读工具

快速结论

没有绝对的赢家,两个工具针对不同的优先级做了优化。如果你想保持 runtime 无关,并在每一个修改 lockfile 的命令上都执行策略审查,选 pnpm。如果你已经把 Bun 用作 runtime,而且 global virtual store 带来的磁盘/速度收益对你很关键,bun install 更有吸引力。两者都默认阻止 postinstall 脚本;区别在于审查点设置的位置。不要在同一个仓库里混用两者——只保留一份 lockfile,一个唯一的真相来源。

pnpmbun install
阅读完整结论

评分对比

图表加载中…

详细评分

详细评分: pnpm 和 bun install ——按类别打分,满分 10 分
分类pnpmbun install
性能
8/10
9/10
学习难易度
7/10
8/10
生态系统
9/10
6/10
社区
8/10
7/10
就业市场
7/10
6/10
面向未来
8/10
8/10

优缺点

pnpm

优点

  • 得益于 content-addressable store,同一版本的包在磁盘上只保留一份,降低磁盘占用
  • 严格的 node_modules 结构默认就能阻止 phantom dependency,无需额外配置
  • 从 12.2-12.3 起,--trust-lockfile/--trust-policy 现在也可以在 remove 和 update 命令上强制启用
  • 通过 allowBuilds allowlist,postinstall 脚本被绑定到一份公开、可审查的列表上(pnpm 10 中叫 onlyBuiltDependencies,v11 起改名为 allowBuilds)
  • 与 Turborepo、Nx、Changesets 之间的 workspace 集成经过多年打磨已趋成熟
  • 运行在 Node.js 之上,与 runtime 选择无关,不会把项目锁死在单一工具上
  • 通过 catalog: 字段,可以在整个 monorepo 中集中管理公共依赖版本
  • 从 12.x 起核心已用 Rust 重写,workspace 发现和 lockfile 解析都实现了并行处理

缺点

  • 基于 symlink 的 node_modules 结构可能与一些老旧/简单的 Node 工具(期望非严格解析方式的工具)产生兼容性问题
  • 手动维护 allowBuilds allowlist,意味着每次新增一个需要 native build 的包都要多一步操作
  • Bun 公布的速度数据是在自己的 linker 之间对比得出的;要了解 pnpm 在同等规模下的表现,需要在自己的仓库里实际测量
  • 没有自己的 runtime——无法提供安装 + 运行 + 测试全部来自单一工具的一体化体验
  • 要把 store 正确纳入 CI 缓存策略(pnpm store path),需要手动配置一个安装步骤

最适合

生产环境使用 Node.js、希望保持与 runtime 无关的团队由 Turborepo 或 Nx 编排的大型 monorepo需要在每一个修改 lockfile 的命令上审查供应链策略的受监管项目磁盘空间受限的 CI runner,或拥有大量相似项目的组织希望从现有 npm/Yarn 项目进行低风险、渐进式迁移的团队

bun install

优点

  • Bun 1.4 引入的可选(opt-in)global virtual store,在 --linker=isolated 模式下能显著加快安装速度
  • postinstall 脚本默认被阻止,trustedDependencies allowlist 对供应链进行明确的审查
  • --offline 和 --prefer-offline 标志能清晰地表达 CI/air-gapped 安装场景
  • isolated installs 模式以类似 pnpm 的方式,从架构层面阻止 phantom dependency
  • bun.lock 这种文本格式的 lockfile(v1.2+ 起默认)在 PR review 中能生成可读的 diff
  • 安装、runtime 和测试运行器都来自同一个工具,为 greenfield Bun 项目提供一体化体验
  • bun install --filter 原生支持基于 workspace 的安装过滤

缺点

  • global virtual store 默认关闭,且只在 isolated linker 下生效;要看到收益,需要在 bunfig.toml 中显式开启
  • isolated linker 只在新建的 workspace/monorepo 项目(configVersion = 1)中默认启用;在单包项目以及 v1.3.2 之前创建的既有项目中,默认仍是 hoisted,因此 phantom dependency 风险需要手动关闭
  • 与 Turborepo/Nx 等工具的集成,相比 pnpm 成熟的时间更短
  • Bun 内置的 trustedDependencies 默认 allowlist 只覆盖来自 npm 的包;file:/link:/git:/github: 类型的依赖必须手动添加
  • 由于安装工具本身是 Bun runtime 的一部分,对想切换到其他 JS runtime 的团队会形成工具锁定
  • 从旧的二进制 bun.lockb 格式迁移到新的文本格式 bun.lock,在既有项目中需要额外的迁移步骤

最适合

已经在生产环境中使用 Bun runtime 的团队对安装速度和 CI 缓存控制要求较高的 greenfield 项目需要在 offline/air-gapped CI 环境中获得明确标志控制的团队希望安装 + 运行 + 测试都来自单一工具的中小型 Bun-only 项目

代码对比

pnpm
// pnpm 12.3 — 通过 allowBuilds 进行受控安装与 workspace 过滤
// package.json(根目录)
{
  "name": "monorepo-root",
  "private": true,
  "packageManager": "[email protected]"
}

// pnpm-workspace.yaml — allowBuilds 在 v10.26.0 中引入,v11 移除了旧名称(onlyBuiltDependencies 等)
packages:
  - "apps/*"
  - "packages/*"

allowBuilds:
  esbuild: true
  sharp: true
  core-js: false

catalog:
  react: ^19.2.3
  typescript: ^5.7.0

// CI 安装步骤(GitHub Actions)
- name: Install dependencies
  run: pnpm install --frozen-lockfile --trust-policy=no-downgrade

// 移除包时,整份 lockfile 会针对当前策略重新校验
pnpm remove left-pad --filter ./apps/web --trust-lockfile

// 仅对发生变更的 workspace 包执行安装
pnpm install --filter "...[origin/main]"

// 把 store 路径加入 CI 缓存键
pnpm store path
bun install
// Bun 1.4 — isolated installs + global virtual store + 离线安装
// bunfig.toml(根目录)
[install]
linker = "isolated"
globalStore = true
exact = false

// package.json
{
  "name": "monorepo-root",
  "private": true,
  "workspaces": ["apps/*", "packages/*"],
  "trustedDependencies": [
    "esbuild",
    "sharp",
    "@prisma/client"
  ]
}

// CI 安装步骤(GitHub Actions)— 锁定且兼容离线
- name: Install dependencies
  run: bun install --frozen-lockfile --prefer-offline

// 查看被阻止的 postinstall 脚本
bun pm untrusted

// 将某个包标记为可信
bun pm trust sharp

// 对特定 workspace 包执行安装
bun install --filter "./apps/web"

// 完全离线安装(不会访问网络)
bun install --offline

结论

没有绝对的赢家,两个工具针对不同的优先级做了优化。如果你想保持 runtime 无关,并在每一个修改 lockfile 的命令上都执行策略审查,选 pnpm。如果你已经把 Bun 用作 runtime,而且 global virtual store 带来的磁盘/速度收益对你很关键,bun install 更有吸引力。两者都默认阻止 postinstall 脚本;区别在于审查点设置的位置。不要在同一个仓库里混用两者——只保留一份 lockfile,一个唯一的真相来源。

获取免费咨询
常见问题

常见问题

要看具体场景。Bun 公布的数据是在自己的 linker 之间做对比:在一个包含 1,400 个包的 React/webpack/Babel/jest fixture 中,热安装在 hoisted linker 下耗时 823.9 ms,在 isolated linker + global store 下为 124.8 ms(Apple Silicon macOS,hyperfine 测得)。pnpm 的 content-addressable store 在热安装时同样依赖磁盘读取,也就是说在合适的条件下两者都很快。你应该用自己仓库的规模和 CI 缓存策略来衡量两个工具之间的实际差距——不要把单一 fixture 的结果直接套到自己的 monorepo 上。

相关博客文章

查看全部文章

相关项目

查看全部项目
全部对比