GoForum › 🌐 V2EX

一个 MonoRepo 复杂系统的部署问题

xhawk · 2026-09-05 21:33 · 0 次点赞 · 11 条回复

我搞了一套财税系统,采用的是 MonoRepo 的构建方式。也就是说,在 APPs 目录下有几十个应用。前端全部用的是 Next.js ,后端用的是 FastAPI 。现在的问题是,代码托管在 GitHub ,镜像则通过阿里云的 ACR 来构建。

核心问题是构建速度非常慢。目前有 11 个应用,其中 4-5 个是前端,6-7 个是后端服务, 后续还在增长。问题在于,有时候我可能只修改了其中一个应用,但很难控制每次只自动构建被修改的那一个。

目前我在 GitHub 上构建时,只有一个分支,也就是 main 分支。如果单独构建每个 APP ,通常只需要 1 到 2 分钟。但一旦有十几个 APP ,每次都要全部构建一遍,速度就会越来越慢,而且我的 APP 数量还在不断增加。我在想,有没有办法在保持 GitHub 上只有一个分支的情况下,也能获得比较快速的构建体验?不知道大家在这方面有没有相关的实践经验?

11 条回复
lujiaosama · 2026-09-05 21:38
#1

我选择不用 MonoRepo 。

xhawk · 2026-09-05 21:43
#2

@lujiaosama 那有啥建议的不, 如果全部分开代码管理, 也很复杂。 因为涉及到系统间的各种调用。

XTTX · 2026-09-05 22:03
#3

vercel 可以选忽略构建步骤, 阿里的你应该问问 AI. 应该是很容易解决的问题

fgwmlhdkkkw · 2026-09-05 22:08
#4

写一个简单的解析 commit msg 的脚本,然后按照约定写 commit msg 。

milkleeeeee · 2026-09-05 22:08
#5
netnr · 2026-09-05 22:13
#6

按 yml 变动构建(增加环境变量 改注释);每个配置里面的矩阵是并行构建

is · 2026-09-05 22:18
#7

建个 ci 的项目把规则写进去,不懂的地方让 agent 帮忙就好了。项目依赖图什么的都好做,可能不太确认的就是 cache 机制。commit 消息也可以做个规范,方便规则匹配

Reficul · 2026-09-05 22:53
#8

上增量编译,bazel 之类的。

xhawk · 2026-09-05 23:03
#9

这个 cursor ai 给的建议, 虽然不是很满意, 但是似乎也只能这么干, 要么就是上面有人建议的采用付费的方式。 ai 的建议, 大概意思意思 acr 构建镜像采用过滤的方式, 代码改了啥, 就构建啥就好了。

结论先说:仓库不要拆。慢的不是 Monorepo ,是「 main 一推就串行重打全部镜像」。

源码继续单仓单分支是对的。行业里 Google / Meta / Shopify 、以及 Nx / Turborepo 的做法都是:代码合在一起,构建按依赖图只打受影响的那几个。 App 越多,越要走这条路,而不是拆仓。

推荐方向(这就是业内标准解):Affected Build + 远程缓存 + 只发变更。

  1. 关掉 ACR 当 CD 引擎。 个人版不适合 10+ 服务。构建改到你们已有的 self-hosted Actions (可并行),结果推杭州 ACR ; Dokploy 只 Redeploy 本次变更的服务。
  2. 按依赖图决定打谁,不要按「整个仓库变了」。 例如改 apps/fis-open-api 只打 open-api ;改 apps/fis-api 打 fis-api 以及依赖它的 open-api ;改 packages/* 只打引用它的前端。用 paths-filter 或一份很小的 affected 映射就够,不必上 Bazel 。
  3. 缓存比拆 context 更值钱。 Dockerfile 已经分层了(先 requirements / package.json )。接上 BuildKit registry cache 后,没改依赖的镜像应是秒级命中。根 context 可以留——你们前端是 pnpm workspace ,强行 per-app context 收益不大。
  4. 中期把「构建期互相 COPY 」收掉。 open-api 不要整份拷贝 fis-api/agents ,改运行时 HTTP / 抽出 packages 共享库; fis-web 的共享 UI 进 packages/fis-shared。耦合一收,affected 扇出就小,速度才会随 App 增加而近似持平。
  5. 发版钉 digest ,不要 8 个 *-latest 整波拉。 未重建的服务保持旧 digest ,避免「构建快了、发布又全量」。
rocmax · 2026-09-05 23:18
#10

建议是每次都全部构建,使用 cache 来解决重复构建耗时的问题。monorepo 强制同步整个项目的版本,防止依赖版本错位,如果选择性构建一部分就回到老路上了。

我们用 turborepo 管理项目,我的经验是:

如果构建产物是 docker 镜像的话使用 layer cache 可以解决大部分问题。需要注意的是构建之前需要用 turbo prune xxx –docker 来提取构建 context 以免混入其它的修改。

如果想直接缓存 nextjs 的构建产物,turborepo 官方有付费构建缓存服务。 也有开源版本比如 https://github.com/ducktors/turborepo-remote-cache 需要自己借助 s3 等来搭建。

另外的一点是在部署 k8s 时全部构建的话产物有共同的 tag ,helm chart 中可以将它统一填到所有子项目中。如果部分购进的话又得管理版本依赖。

members · 2026-09-05 23:23
#11

问题在于,有时候我可能只修改了其中一个应用,但很难控制每次只自动构建被修改的那一个。

难在哪里? 我们的方案是构建过程中运行一个脚本,git diff merge-base 有哪些文件改动,构建对应的服务。

有一说一 monorepo 是真的恶心。

添加回复
你还需要 登录 后发表回复

登录后可发帖和回复

登录 注册
主题信息
作者: xhawk
发布: 2026-09-05
点赞: 0
回复: 0