大多数团队把“monorepo vs multi-repo”看作一道单选题——选一个方向,一锤定音。但这个做智慧城市平台的团队偏偏走了第三条路:把6个应用塞进4个代码仓库,一半大一统、一半独立成仓。这不是和稀泥,而是被部署周期和团队归属推出来的结果。
整个系统里,有一个 API 后端和五个前端应用:面向居民、保安、小区员工的三个移动端 App,以及一个管理后台、一个运营仪表盘和一个营销网站。所有应用的接口都指向同一个 API,但它们的发布节奏、谁来改、怎么测,完全不在一个频道上。
仓库切分就变成了这样:
main-platform 仓库里收起 API、营销网站、管理后台和仪表盘,四个模块同在一个 monorepo 里呼吸。而三个移动端 App——居民端、保安端、员工端——各自独占一个仓库,互不干扰。
为什么把移动端踢出去?因为部署速度的差异大得像两个世界。
Web 应用走的是 push 即部署:代码合入主干,CI 跑完,CDN 几分钟内刷新,回滚也是秒级,中间没有任何审批闸门。移动端就完全不一样了:要打出 release APK,提交到 Google Play(和 Apple App Store),等审核,再走分阶段逐步推送。一个版本的度量单位是天,不是分钟。而且一旦发布出去有坑,修起来代价极高——你只能再提一个补丁,继续等审核,期间在线的就是那个带 bug 的版本。
这种级别的部署工具体系自然要分开。移动端需要独立的 release 流程、独立的语义化版本(每个仓库一个 release-please)、独立的 EAS 构建配置,以及干净到能直接丢给审核人员的 changelog。如果硬往 Web 仓库里塞,每次打移动包都得拖着一堆不相关的 Web 变更,发布说明也会变成乱炖。独立成仓以后,每个移动 App 的发布历史就是一条清晰的时间线。
那为什么又把 API 和三个 Web 前端留在同一个锅里?因为它们改得实在太同步了。
随便一个新功能,八成要同时碰 API 和至少一个 Web 前端。比如加个账单模块,就得开新的接口端点、在 React 里建新页面,两边一起变。放在一个仓库里,一个 PR 就能覆盖整条链路:CI 做全量校验,reviewer 能一眼看到数据层和 UI 层的联动,不用再去别的仓库翻上下文。反过来,如果切成两个仓,每个功能 PR 都得跨库“套娃”——主仓库一个,Web 仓库一个,靠 linked issue 来回指,协同开销直线上升。
但仓库缝合处仍然藏着摩擦源。一旦 API 新增端点或改了契约,移动端仓库就需要同步跟进。这时就会触发典型的跨仓工作流:主干功能的需求 issue 挂在 main-platform 仓库,每个移动端仓库再各有一个子 issue 反向引用,PR 里也互相挂链接。团队把所有跨仓依赖做成显式关联,而不是靠口头对齐,才没让这种混合架构在协作上漏成筛子。
回看这个四仓库布局,它没有追求“单一真相源”的理想化 monorepo,也没有放任每个应用各建山头的多仓分散。它把高频联动的部分聚在一起,把节奏差异巨大的部分剥离出去,让架构自然地匹配了团队的交付心跳。这个选择不是完美的,但它证明了:仓库结构不必非黑即白,能贴住自己发布节拍的设计,就是当下最好的设计。
热门跟贴