【声明】本博客所有内容均为个人业余时间创作所述技术案例均来自公开开源项目如GithubApache基金会不涉及任何企业机密或未公开技术如有侵权请联系删除背景上篇 blog【Agent】【OpenCode】项目配置子包版本)分析了package.json中的version配置字其中version指的是子包版本而非整个项目版本其中根目录package.json的version通常代表整个 Monorepo 脚手架的版本业务代码一般不依赖它OpenCode 在这里并没有定义项目的版本号而子包package.json的version则代表该子包自身的语义化版本接着分析了子包版本管理的两种模式锁定版本模式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没介绍这里private为true刚好就验证了之前的分析OpenCode 使用的是应用级别的 Monoreponpm/yarn/pnpm 看到private为true时会拒绝执行 npm publish此时的版本号就可以随意调整不影响任何外部用户接着是export配置下面分析下库级别 Monorepo 和应用级别 Monorepo 在export配置上的区别维度库级别OpenCode 应用级别配置类似./button等精确路径./*./src/*.ts通配符指向dist/等构建产物 部分源码全部指向src/原始 TypeScript 源码消费者外部 npm 用户 内部包仅内部包运行时Node.js 加载编译后的 JSMJSBun 直接运行.ts源码设计意图讲究兼容提供稳定公共 API开发时零构件源码级实时引用OK本篇先到这里如有疑问欢迎评论区留言讨论祝各位功力大涨技术更上一层楼更多内容见下篇 blog【Agent】【OpenCode】项目配置tsconfig.json 与 package.json