跳转到内容

Bun Monorepo 与 10 包工作空间设计

Bun Monorepo 与 10 包工作空间设计

学习目标

  • 理解 Bun workspaces 的包分层规则
  • 掌握 Bun 构建命令与外部依赖 shim 策略
  • 识别 Node.js API 在 Bun 中的兼容性差异

项目实践

10 个内部包的分层

package.jsonworkspaces 字段定义了 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-enginemodel-coreprompts-core — 业务逻辑,无外部依赖
  • 工具包hashline-coreast-grep-corecomment-checker-core — 可独立测试和复用
  • 基础设施包utilsboulder-stateagents-md-core — 跨包共享的基础设施

为什么选 Bun

  • 原生 TypeScript:无需 tsc 编译即可运行,bun run 直接执行 .ts 文件
  • 极速构建bun build 直接输出 ESM,无需 esrollup/webpack 配置
  • 内置测试bun test 替代 jest/vitest
  • workspace 支持:内部包通过 workspace:* 版本引用,自动解析

构建流程

Terminal window
# 主构建
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.tsresolveHomeDirectory() 函数)

问题与规避

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,因为速度优势和一体化体验对快速迭代的插件项目至关重要。

参考来源