Monorepo 的价值
最近又开始研究起 monorepo 了,背景是组内的虽然已经从 multi-repo 转到 monorepo 两年多,但是因为长期没有人治理,所以还是有很多问题。最近我们方向把这摊子事情整个接过来了,所以需要再深入思考一下这件事。
- 本文所描述的只是前端场景下的 monorepo,其他场景下的 monorepo 本文不做讨论。
- 本文是我在研究 monorepo 的过程中的一些思考/总结,所以可能会有一些错误的地方,欢迎指正。
- 后续有任何新的想法,我会在本文中更新,✏️ Last update: 2024/01/20
multi-repo(poly-repo) 的问题
简单说说 multi-repo 的问题,因为重点还是要聊 monorepo 的价值。
- 基建重复建设成本:每个项目都需要开发人员独自维护一整套基础建设,这个成本是非常高的。
- 人员调度成本:在公司内部,人员在组内不同项目之间的调度是非常频繁的,而 multi-repo 的情况下,每个项目都有自己的基础建设,这就导致了人员调度的成本非常高,因为每个项目都需要重新熟悉一遍基础建设。
- 维护公共模块成本:想简单修一修公共模块的问题特别麻烦,clone -> link -> 研究如何开发 -> 修 -> commit -> push -> publish -> update -> test -> merge,这个过程非常繁琐,而且还有很多坑,例如版本号的管理、依赖的管理等等,同时改动的影响面也无法很好的评估
- 代码规范:每个库都要思考一下自己的规范怎么做,这个成本也是非常高的,而且到底有没有做到统一也是个问题
先整理这些痛点问题吧,别的问题可以没这些问题这么直观。
monorepo 能解决什么
我们可以从两个角度来看待 monorepo 的价值。
1. 团队角度
统一基础设施
对团队来说,monorepo 最大的价值是基础设施的统一,通过统一所有的基础工具链,来降低所有工程师的研发成本,这里的基础设施包括但不限于:
- 构建工具:所有的项目都使用同一套构建工具,可以统一构建的配置,减少重复的工作。
- CI/CD 工具:monorepo 让统一 CI/CD 工具变得更加容易
- 代码规范/风格:对于代码风格的约束也更加容易实现和管理
- 单测/代码提交/版本发布等等:都可以进行统一,这样就不需要每个项目/方向都去思考、实现自己的方案
在这些基础设施统一之后,团队的研发效率会显著提升,因为大部分的工程师都不需要再去关心这些基础设施的事情,避免大家重复造一些 infra 的轮子,可以专注于业务的开发。
而在 multi-repo 的情况下,每个 repo 都有自己的基础设施,这就导致了每个 repo 都需要维护自己的基础设施,这样就会导致团队的研发效率降低。从我个人的工作经验来开,这部分的开销是不小的,因为每个人都会觉得自己的方案会更好(都有造轮子的心,但是造出来不一定比别人的好🤣)。
项目依赖全局唯一
在 monorepo 的情况下,项目之间的相互依赖不再依靠 npm 包,而是直接依赖于项目本身,这样就可以保证项目之间的依赖是全局唯一的。
全局唯一后,内部依赖的升级就可以有更全面的覆盖,而不是像 multi-repo 的情况下,每个项目都需要自己去升级依赖,这样就会导致依赖升级的工作量成倍增加。
同时因为 monorepo 的架构,依赖在做升级的时候也可以很方便的分析出依赖的影响范围,这样就可以更好的控制风险。
当然,这又侧面的要求了内部依赖的代码质量,因为统一的内部依赖版本会导致风险会暴露更快,所以代码质量也必须更高。不过在 multi-repo 的情况下,不是说这个风险就不存在了,只是因为依赖升级需要每个项目都去做,所以会暴露得更慢一些而已。
理论上做到更极致的点是做到底层依赖的全局统一,如 lodash, react 等等,这样可以更好的解决依赖升级、代码重否构建以及技术债务的问题(当然成本也相对较高,尤其是在第一次统一时)
公共依赖的代码质量重视程度被加强
在 multi-repo 的情况下,公共依赖项目的单测往往会被忽略,在 multi-repo 下,因为是以 npm 包的形式发布,所以一些问题不会立即暴露出来,且公共依赖常常会让业务自己升级的时候去做人工测试,这样就导致公共依赖项目的单测往往会被忽略。而且更恶劣的情况是,在很长时间不升级后,业务方宁愿自己去 fork 一个老的版本做一些修改,也不愿意去升级公共依赖项目,因为风险实在太大了。
但是在 monorepo 的情况下公共依赖项目的单测就会被重视起来,因为公共依赖项目的问题会影响到所有的项目,而且是会立即暴露出来,这就侧面要求公共库的代码质量。
也就是说,如果你在 monorepo 场景下,不重视公共依赖的单测,那么公共代码将变的无法维护,所以这就迫使你必须重视公共依赖的单测。
团队角度的其他价值
这里再补充一些小的点(不会展开解释太多具体原因)。
- 方便代码质量管控:全局代码扫描、全局单测、全局覆盖率、全局 lint 等等
2. 个人角度
monorepo 对于整个团队的收益很大,但是对个人的收益可能没那么明显,而且一些同学还会认为,monorepo 统一的方式限制了一些个人的发挥,这里我简单整理几个对于个人的价值。
项目切换成本低
基建的统一让切换项目的成本降低,monorepo 内部的项目切换不需要每次切换项目都学习&习惯新的基建。
更专注业务的开发
由于基建的统一,个人可以更专注于业务的开发,而不需要去关心基建的事情,这样就可以更专注于业务的开发。
如果想做技术上的建设时,也需要更多的考虑点,过更多的技术 review,以保证基础建设的质量。
代码共享方便学习优秀实践
因为所有的业务+基建代码都在一个仓库,所以可以很方便学习团队内部的优秀代码实践,以及团队内部避免重复造一些轮子。
同时也因为代码共享,一定程度上避免了糊屎的情况,因为自己的代码会被更多的人看见(其实也未必,如果不能做好代码质量管理的话,就算 monorepo 可能也解不了这个问题),但是我从我个人角度上看是成立的。
做工具/公共业务代码变更时,方便梳理出影响范围
因为清晰地知道自己变更代码在哪些地方被使用,所以可以更好的控制自己对代码变更的风险。
monorepo 产生新的问题
因为代码管理模式的变化,所以必然会产生不少问题。
这个其实也是一个非常大的点,我会开一个新的文章总结(其实因为懒,想早点把 monorepo 价值的文章结了...),这里暂时不补充。
总结
文章不长,就不总结啥了,补一下自己后续可能会更新的点:
- monorepo 产生的问题以及解决方案
- monorepo 应该如何落地
- monorepo 在不同规模的团队中的应用场景
- monorepo 中的代码质量管理
- monorepo 技术选型
- monorepo + pnpm 下如何锁定依赖