Monorepo(Monolithic Repository)翻译过来就是一个代码仓库。
Multirepo(Multiple Repositories)翻译过来就是多个代码仓库。
它们都是项目管理的一种策略,而不是一种技术,各有利弊。
当我们开发一个项目时,项目可能分成好几个子项目,它们逻辑各自独立,又可能相互关联。
这个时候,使用一个仓库来管理代码,还是多个仓库来管理,影响的是团队的开发流程。
这可能涉及项目的依赖包管理、CI/CD、开发效率、事故追责等。
Monorepo
与哪种语言无关,各种语言都有各自相关的框架技术支持。
那么使用单一仓库有什么好处呢?
- 代码所有人可见。
- 别人可以看你代码,直接帮你改 bug
- 每天都看同一个远程仓库的 issue/commit,你可以知道别人修好 bug 没
- 统一代码风格
- 可以使用统一的代码检测规则,更方便读懂别人代码
统一依赖管理 :::info 例子一:
假如说有 A、B、C、D 四个仓库,都引用了 M 依赖。随着 M 的版本升级,提供了新功能/大改版,A 就升级了,其他没有升。A 用新版本开发,其余用旧版本,随时时间推移,版本迭代,哪天 B、C、D 需要新版本的功能,升了一下。可能一堆代码要改。
不如单个仓库存 A、B、C、D,要升一起升,要改一起改,不至于版本迭代,改得更多。 :::统一 CI/CD
性能更好
- 项目被拆解后,有些查询计算需要的时间更短。
- 比如
git blame
查询 commit 的时候,由于拆分后 commit 比较少,耗时短
- master 分支出错时,影响较小
- 多个仓库,多个 master,万一哪个仓库出错,对别的仓库的开发影响较小
- 学习成本更低
- 拆分多个代码仓库后,对高内聚低耦合要求更高,写代码会更注意,别人也不容易乱写乱引用
- code reviews
- pull request 后的通知相比单一仓库来说,更少,不会太烦人
用什么技术实现 monorepo 呢
:::info
- Bazel:由 Google 发布,部分基于他们自己的构建系统 (Blaze)。Bazel 支持多种语言,并且能够大规模构建和测试。
- Buck:Facebook 的开源快速构建系统。支持多种语言和平台上的差异化构建。
- Pants:Pants 构建系统是与 Twitter、Foursquare 和 Square 合作创建的。目前,它仅支持 Python,未来还将支持更多语言。
- RushJS:微软发布的可扩展的 JavaScript 单仓库管理器,能够从单个存储库构建和部署许多包。
Monorepos 正受到越来越多的关注,尤其是在 JavaScript 中,如以下项目所示:
- Lerna:JavaScript 的 monorepo 管理器。与 React、Angular 或 Babel 等流行框架集成。
- Yarn Workspaces:使用单个命令在多个位置安装和更新 Node.js 的依赖项。
- ultra-runner:用于 JavaScript 的 monorepo 管理的脚本。使用 Yarn、pnpm 和 Lerna 插件。支持并行构建。
- Monorepo builder : 用 PHP 写的 monorepos 包管理工具。
:::
目前常见的是使用 lerna 来管理前端项目,它默认使用 npm,由于 npm@7 开始也支持了 workspaces,所以不一定非要用 yarn 的 workspaces。
如何建立项目,可以参考如下文章:
《All in one:项目级 monorepo 策略最佳实践》
《lerna+yarn workspace+monorepo项目的最佳实践》
《Monorepo 的这些坑,我们帮你踩过了!》参考文章
《What is monorepo? (and should you use it?)》
《Workspaces in Yarn》
《Monorepos in JavaScript & TypeScript》