这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
前言
随着前端工程日益复杂,某些业务或者工具库通常涉及到多个仓库,那么时间一长,多个仓库开发弊端日益显露,由此出现了一种新的项目管理方式——Monorepo
什么是Monorepo
Monorepo 的意思是在版本控制系统的单个代码库里包含了许多项目的代码。这些项目虽然有可能是相关的,但通常在逻辑上是独立的,并由不同的团队维护。
有些公司将所有代码存储在一个代码库中,由所有人共享,因此 Monorepos 可以非常大。例如,理论上谷歌拥有有史以来最大的代码库,每天有成百上千次提交,整个代码库超过 80 TB。其他已知运营大型单一代码库的公司还有微软、Facebook 和 Twitter。
Monorepos 有时被称为单体代码库(monolithic repositories) ,但不应该与单体架构(monolithic architecture) 相混淆,单体架构是一种用于编写自包含应用程序的软件开发实践。这方面的一个例子就是 Ruby on Rails,它可以处理 Web、API 和后端工作。
单一代码库(monorepos) vs 多代码库(multirepos)
与单一代码库相反的是多代码库(multirepos) ,每个项目都储存在一个完全独立的、版本控制的代码库中。多代码库是很自然的选择——我们大多数人在开始一个新项目时都愿意开一个新的代码库,毕竟,谁都喜欢从 0 开始.
从多代码库到单一代码库的变化就意味着将所有项目移到一个代码库中。
当然,这只是开始。当我们开始重构和整合时,困难的工作就来了。
$ mkdir monorepo
$ git init
$ mv ~/src/app-android10 ~/src/app-android11 ~/src/app-ios
$ git add -A
$ git commit -m "My first monorepo"
多代码库不是微服务(microservices) 的同义词,两者之间并没有耦合关系。事实上,我们稍后将讨论将单一代码库和微服务结合起来的例子。只要仔细设置用于部署的 CI/CD 流水线[2],单一代码库就可以托管任意数量的微服务。
Monorepo 文化
Monorepos 已经存在很长时间了。三十年来,FreeBSD 一直使用 CVS 和后来的 subversion monorepos[6]进行开发和包分发。
许多开源项目已经成功使用了单一代码库。例如:
-
Laravel:一个用于 Web 开发的 PHP 框架。
-
Symfony:一个用 PHP 编写的 MVC 框架。有趣的是,他们已经为每个 Symfony 工具和库创建了只读存储库,这种方法被称为分库(split-repo) 。
-
NixOS:一个用单一代码库发布包的 Linux 发行版
-
Babel:一个用户 Web 开发的流行的 JavaScript 编译器,其单一代码库包含了完整的项目及其所有插件。
-
此外,React、Ember和 Meteor等前端框架都使用单一代码库。
然而,真正的问题是商业软件是否能从单一代码库中获益。考虑到这些优点和缺点,让我们来看一些已经尝试过的公司的经验。
Monorepo 管理最佳实践
基于这些单一代码库的故事,我们可以定义一套最佳实践:
- 定义一个便于探索的统一的目录组织。
- 维护分支整洁,保持较小的分支,考虑采用基于主干的开发。
- 为每个项目使用固定的依赖项,一次升级所有依赖项,迫使每个项目都跟上依赖项。只为真正的例外情况保留例外。
- 如果正在使用 Git,学习如何使用 shallow clone和 filter-branch来处理大容量代码库。
- 货比三家,寻找像 Bazel 或 Buck 这样的智能构建系统,以加速构建和测试。
- 如果需要限制对某些项目的访问,请使用 CODEOWERS。
- 使用 Semaphore等 CI/CD 云平台来大规模测试和部署应用程序。