为什么选了 Monorepo?
当时团队有 5 个前端项目,共享一些工具函数和组件。每次改公共代码,都要发 npm 包,然后各个项目再更新依赖,很麻烦。
看到 Babel、React、Vue 这些大项目都用 Monorepo,觉得这肯定是趋势。加上 Lerna、Nx 这些工具看起来很成熟,就决定试试。
刚开始确实很爽
改完公共代码,直接就能在其他项目里用,不用发包。代码跳转也方便,IDE 能直接找到定义。看起来一切都很美好。
但问题很快就来了
CI/CD 变慢了
以前每个项目独立 CI,改哪个项目就只跑哪个。现在改一个包,所有依赖它的项目都要重新构建和测试。
我们用的是 Nx,虽然它说能智能识别变更,但实际用下来,还是经常误判。有时候只改了一个 README,结果触发了整个项目的构建。
依赖管理变复杂
Monorepo 里,包之间的依赖关系很容易搞混。A 依赖 B,B 依赖 C,C 又依赖 A,这种循环依赖在 Monorepo 里特别容易产生。
而且版本管理也麻烦。虽然可以用 workspace:*,但有时候需要发布到 npm,版本号怎么管理?每个包独立版本,还是统一版本?都是问题。
Git 历史变乱
所有项目在一个仓库里,Git 历史就混在一起了。想找某个项目的某个功能,要在整个仓库的历史里翻,很费劲。
虽然可以用 git log --follow -- packages/xxx 过滤,但总归不如独立仓库方便。
权限管理困难
有些项目是公开的,有些是私有的。在 Monorepo 里,要么全公开,要么全私有,很难做细粒度控制。
什么时候该用 Monorepo?
用了一年多,我觉得 Monorepo 适合这些场景:
- 大型团队:有专门的工具链团队维护 Monorepo 工具。
- 强耦合项目:项目之间依赖关系复杂,经常需要一起改。
- 统一发布:需要同时发布多个包,版本号要同步。
- 代码共享频繁:公共代码更新很频繁,发 npm 包太麻烦。
什么时候不该用?
如果:
- 团队小于 10 人
- 项目之间相对独立
- 公共代码更新不频繁
- 没有专门的工具链支持
那还是用 Multirepo 更省心。发 npm 包虽然麻烦点,但至少不会因为工具问题拖慢开发。
我们的解决方案
最后我们做了个折中方案:
- 核心工具包还是用 Monorepo,因为更新频繁。
- 业务项目独立仓库,通过 npm 依赖工具包。
- 工具包用 Changesets 管理版本,发布流程自动化。
这样既享受了 Monorepo 的便利,又避免了它的复杂性。
如果一定要用 Monorepo
如果决定要用,建议:
- 选成熟的工具(Nx、Turborepo、Rush),别自己造轮子。
- 做好 CI/CD 优化,用缓存和并行构建。
- 建立清晰的包依赖规范,避免循环依赖。
- 定期清理不用的包,保持仓库整洁。
总结
Monorepo 不是银弹。大厂用得好,是因为他们有专门的团队维护工具链。小团队盲目跟风,很容易被工具拖累。
选技术方案,还是要看实际需求。如果 Multirepo 够用,就别折腾 Monorepo。如果确实需要,也要做好心理准备,这玩意儿比想象中复杂。
评论区