Bun Monorepo 与 10 包工作空间设计
Bun Monorepo 与 10 包工作空间设计
学习目标
- 理解 Bun workspaces 的包分层规则
- 掌握 Bun 构建命令与外部依赖 shim 策略
- 识别 Node.js API 在 Bun 中的兼容性差异
项目实践
10 个内部包的分层
package.json 的 workspaces 字段定义了 10 个内部包:
packages/├── rules-engine/ # 规则注入引擎├── ast-grep-core/ # AST-Grep 核心逻辑├── ast-grep-mcp/ # AST-Grep MCP 服务器├── utils/ # 共享工具函数├── model-core/ # 模型适配核心├── prompts-core/ # 提示词管理核心├── comment-checker-core/ # 注释检查器核心├── hashline-core/ # Hashline 编辑协议核心├── boulder-state/ # Boulder 状态管理└── agents-md-core/ # AGENTS.md 生成核心分层规则:
- 核心逻辑包:
rules-engine、model-core、prompts-core— 业务逻辑,无外部依赖 - 工具包:
hashline-core、ast-grep-core、comment-checker-core— 可独立测试和复用 - 基础设施包:
utils、boulder-state、agents-md-core— 跨包共享的基础设施
为什么选 Bun
- 原生 TypeScript:无需
tsc编译即可运行,bun run直接执行.ts文件 - 极速构建:
bun build直接输出 ESM,无需 esrollup/webpack 配置 - 内置测试:
bun test替代 jest/vitest - workspace 支持:内部包通过
workspace:*版本引用,自动解析
构建流程
# 主构建bun build src/index.ts --outdir dist --target bun --format esm \ --external @ast-grep/napi --external zod
# tsc 类型检查(不输出)tsc --emitDeclarationOnly
# CLI 构建bun build src/cli/index.ts --outdir dist/cli --target bun --format esm
# Schema 生成bun run script/build-schema.ts外部依赖 Shim
@ast-grep/napi 作为外部模块,不打包到 dist 中:
--external @ast-grep/napi:Bun 不打包原生绑定- 运行时通过 npm 安装的原生模块提供
- 避免打包后二进制文件不兼容
Node.js API 兼容性
Bun 实现了大部分 Node.js API,但有细微差异:
os.homedir():Bun 缓存首次调用结果,测试中process.env.HOME变更后不生效- 解决方案:直接读取
process.env.HOME而非使用os.homedir()(见src/plugin-config.ts的resolveHomeDirectory()函数)
问题与规避
os.homedir() 缓存陷阱
问题:Bun 缓存 os.homedir() 的首次结果,测试中设置 process.env.HOME 后不生效。
规避:直接读取环境变量:
const homeDir = process.env.HOME ?? process.env.USERPROFILE ?? homedir()原生模块加载失败
问题:@ast-grep/napi 在不同平台上的二进制文件路径不同。
规避:通过 optionalDependencies 按平台自动安装正确的二进制包。
设计取舍
Bun vs npm/pnpm + esbuild
| 方案 | 优势 | 代价 |
|---|---|---|
| Bun | 一体化(运行时 + 构建 + 测试)、速度快 | 生态较新、Node.js API 差异 |
| npm/pnpm + esbuild | 生态成熟、兼容性确定 | 配置复杂、多工具链 |
Oh-My-OpenAgent 的选择:Bun,因为速度优势和一体化体验对快速迭代的插件项目至关重要。