123、【Agent】【OpenCode】项目配置(应用级 Monorepo)

【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除

背景

上篇 blog

【Agent】【OpenCode】项目配置(子包版本)

分析了 package.json 中的 version 配置字,其中 version 指的是子包版本,而非整个项目版本,其中根目录 package.jsonversion 通常代表整个 Monorepo 脚手架的版本,业务代码一般不依赖它,OpenCode 在这里并没有定义项目的版本号,而子包 package.jsonversion 则代表该子包自身的语义化版本,接着分析了子包版本管理的两种模式:锁定版本模式(Fixed/Locked Mode,所有子包的 version 保持一致,OpenCode 当前所用的),与独立版本模式(每个子包的 package.json 里的 version 各不相同,发布时各自独立递增),最后提到了 Git 里的版本 ≠ npm 上的版本,下面继续分析

OpenCode

关于版本号,这里最后再更正下补充一个信息,从历史的提交记录来看,基本都是由 OpenCode 单独提一个合入请求 MR 进行更新的,与上篇 blog 提到的由工具自动计算版本号填入还不太一样,并且版本更新时间也不是固定的

可以看到单次 MR 内,只有更新版本号这一个动作,这个动作会更新掉所有子包里的版本号,并将修改同步到 bun.lock

结合这里的历史提交记录,可以推断出 OpenCode 的子包大概是不用发布到 npm 的属于应用级别的 Monorepo,而不是库级别的 Monorepo,下面做个对比分析

维度 库级别 Monorepo(比如 Babel/React) 应用级别 Monorepo(比如 OpenCode)
子包消费者 外部 npm 用户 仅仓库内部的其他子包
npm publish 必须发布,版本号是公共契约 不需要,版本号只做内部标识用
版本号意义 SemVer 兼容承诺 构建、缓存、调试标记
版本统一原因 让用户知道哪些包互相兼容 让内部依赖解析简单,CI 缓存命中率高
version 的 MR 由 CI 自动回写或 linked 机制触发 手动提,因为只是内部事务

这种统一的版本在应用级别的 Monorepo 也有实际价值 ,比如调试追溯 时,用户报 Bug 说 xxx.xxx.xxx 版本有问题,开发者能立刻定位所有子包的源码状态,而不需要查每个子包各自的版本

回到 MR,这里可以看到维护者在准备一个新 release 时,手动把内部版本号对齐到一个新值,这个操作和 npm 无关,只是为了让仓库内部的版本标记保持一致,而之后的 CI 可能只是打个 Tag,构建产物,推送到 Github 等,不涉及到 npm publish 发布,与 npm 契约无关

OK,再回到 package.json,这里还有个关键配置字 private 没介绍

这里 privatetrue,刚好就验证了之前的分析,OpenCode 使用的是应用级别的 Monorepo,npm/yarn/pnpm 看到 privatetrue 时,会拒绝执行 npm publish,此时的版本号就可以随意调整,不影响任何外部用户

接着是 export 配置

下面分析下库级别 Monorepo 和应用级别 Monorepo 在 export 配置上的区别

维度 库级别 OpenCode 应用级别
配置 类似 ./button 等精确路径 ./*./src/*.ts 通配符
指向 dist/ 等构建产物 + 部分源码 全部指向 src/ 原始 TypeScript 源码
消费者 外部 npm 用户 + 内部包 仅内部包
运行时 Node.js 加载编译后的 JS,MJS Bun 直接运行 .ts 源码
设计意图 讲究兼容,提供稳定公共 API 开发时零构件,源码级实时引用

OK,本篇先到这里,如有疑问,欢迎评论区留言讨论,祝各位功力大涨,技术更上一层楼!!!更多内容见下篇 blog

【Agent】【OpenCode】项目配置(tsconfig.json 与 package.json)