Monorepo 与 Workspaces
使用 Bun Workspaces、Catalogs、isolated linker 和过滤命令维护可复现 Monorepo
最后更新于
最后核验:2026-08-02,Bun 1.3.14。
什么时候需要任务编排器
| 仓库规模 | 建议 |
|---|---|
| 少量包、脚本简单 | 只用 Bun Workspaces |
| 中型 Web Monorepo,需要缓存 | Bun Workspaces + Turborepo |
| 企业边界、Generator 和项目图 | 评估 Nx |
| TypeScript、Rust、Go 等多语言 | 评估 moon 或现有统一构建系统 |
Bun 负责依赖、工作区和脚本执行;Turborepo、Nx、moon 负责的任务图、缓存或多语言工具链不是 Bun Workspaces 的同义词。
根配置
{
"name": "acme",
"private": true,
"packageManager": "bun@1.3.14",
"workspaces": {
"packages": ["apps/*", "packages/*"],
"catalog": {
"typescript": "6.0.3",
"zod": "4.1.8"
}
},
"scripts": {
"typecheck": "bun run --filter '*' typecheck",
"test": "bun run --filter '*' test",
"build": "bun run --filter '*' build"
}
}这里的第三方版本只是本页核验快照,不是长期的 latest 建议。升级 Catalog 会影响所有引用它的 Workspace,应作为可审查的依赖变更处理。
子包引用 Catalog 和内部包:
{
"name": "@acme/api",
"private": true,
"dependencies": {
"@acme/contracts": "workspace:*",
"zod": "catalog:"
}
}发布公开包时,Bun 会把 workspace: 和 catalog: 解析成普通版本;发布前仍应检查 tarball 内容和最终 manifest。
优先使用 isolated linker
[install]
linker = "isolated"isolated linker 让包只能访问自己声明的依赖,可更早发现幽灵依赖。老工具、代码生成器或原生依赖如果只支持扁平 node_modules,应先记录失败证据,再针对仓库回退 hoisted,不要在两个模式间随机切换。
过滤安装和脚本
bun install --filter './apps/api'
bun run --filter '@acme/*' typecheck
bun run --filter '*' test
bun ci过滤器减少本地工作量,但合并门禁仍应验证所有受影响 Workspace。任务有前后依赖或需要远程缓存时,用任务编排器表达依赖图,不依赖目录顺序碰巧正确。
推荐边界
apps/
web/ # UI 与框架边界
api/ # HTTP / MCP 入口
worker/ # 异步任务
packages/
core/ # 纯业务规则,不直接依赖 Bun API
contracts/ # Schema、DTO、RPC/OpenAPI 类型
database/ # 数据访问和迁移
config/ # 经过校验的配置读取
observability/ # 日志、Trace、Metricscore 保持纯 TypeScript,Bun.SQL、Redis、S3、Bun.serve 放在具体 App 或 Adapter 层。这样既能使用 Bun 原生能力,也能对业务逻辑做无运行时单元测试。
CI 与发布门禁
- 精确安装经过验证的 Bun 版本;
bun ci验证根 manifest 与bun.lock;- 检查 Workspace 之间没有未声明 import;
- 运行受影响任务,主分支再运行完整任务图;
- 发布前检查
workspace:/catalog:转换后的 package manifest; - 原生依赖至少在目标操作系统和 CPU 架构安装、测试一次。
一个仓库只保留一个依赖真相源
不要长期同时维护 bun、npm、pnpm 或 Yarn 的多个锁文件。混合运行时可以存在,但依赖解析和发布流程必须明确由哪一个锁文件负责。
官方参考:Workspaces、Catalogs、bun install。