在企业级项目开发中,面对多个项目的管理,monorepo 和 multirepo 是两种常见的代码管理方案,它们各有特点与优劣,下面我们来详细了解一下。
一、基本概念
- monorepo:“mono”在英语中有“单一的、单独的”之意,“repo”是“repository”(仓库)的简写,所以 monorepo 指的就是使用单一仓库来管理多个项目。那什么算是一个仓库呢?一般来讲,一个仓库是指通过版本控制系统(git)进行管理的代码库。在 git 的语境下,一个仓库通常是指一个包含“.git”子目录的目录,“.git”这个目录包含了所有版本的提交历史、分支以及标签等信息,也就是说,一个通过 git 初始化后的目录才算得上是一个仓库。
- multirepo(polyrepo):与 monorepo 相对应,multirepo 指的是使用多个仓库管理多个项目,通常是一个项目对应一个仓库。
二、monorepo
- 产生背景与应用现状:monorepo 这种多项目管理方式乍看似乎违背直觉,毕竟我们习惯认为多个项目就该对应多个仓库。但随着公司业务发展,类似项目增多,一个项目对应一个仓库会暴露出不少弊端。比如,每个项目都要搭建
eslint + prettier + commitLint + styleLint
等代码规范校验;每个项目都要搭建许多常用组件并创建公共 utils 函数;各个项目的主要依赖库(如 vue、elementPlus)版本可能不一致,且存在重复安装;有时候组件改动会涉及多个项目都要手动更改等情况。
鉴于在不同项目业务中,常常会用到公共的组件库以及公共依赖,采用 monorepo 风格管理多个项目就较为合适了。它能让多个模块共享同一个仓库,进而共享同一套构建流程、代码规范等,在存在公共组件或工具函数时,查看代码、修改 bug、调试等操作都会变得很便捷。
目前,很多知名公司都采用 monorepo 风格管理内部多个项目,例如:
- 谷歌(Google):将所有项目和库存储在一个称为 Piper 的庞大代码库中,便于管理依赖关系、共享代码以及跨项目进行更改。
- Meta:其代码库涵盖多个项目,像 React、React Native 和 Jest 等,通过 monorepo 策略统一管理这些项目的代码和依赖关系。
- 微软(Microsoft):部分项目采用了 monorepo,如 Windows 操作系统和 Visual Studio 代码编辑器,以此来管理相关代码。
- Twitter:将所有代码存储在名为 Pants 的代码库中,有助于更好地管理依赖关系并提高代码复用率。
- Uber:使用名为“Fusion.js”的 monorepo 代码库管理众多前端项目,能更有效地共享代码并进行跨项目更改。
- monorepo 的优势:
- 代码共享:这是 monorepo 的主要优势之一,方便项目间共享代码,提高复用率,降低维护成本。
- 统一的依赖管理:所有项目和库的依赖关系都在同一个地方进行管理,有助于减少版本冲突和依赖问题,团队能更轻松地保持依赖关系的一致性并进行更新。
- 简化代码共享:由于所有项目处于同一个代码库,开发人员能便捷地共享代码和资源。
- 更容易进行跨项目更改:对多个项目进行协调更改变得简单,因为它们都在同一个地方,降低了跨项目更改的复杂性和风险。
- 更好的跨团队协作:开发人员可以轻松查看其他项目的代码和进度,有助于提高团队之间的协作效率。
在企业开发中,如果你选择使用 monorepo 风格来管理你的多个项目,那么通常是将公共的组件、工具库、api 进行一个抽离共享。
- monorepo 的缺点:
- 代码库的规模:随着项目数量增加,代码库会变得十分庞大,管理难度上升。
- 缺乏独立版本的控制:所有项目共享相同的提交历史,这可能导致独立版本的控制变得极为复杂。
- 权限和安全性问题:所有项目都在同一个代码库内,权限控制难度加大,安全性相对变弱。
- 工具和基础设施的要求:项目增多、代码库变大时,需要特定工具和基础设施辅助管理,像谷歌就采用自定义的代码库及构建系统来管理庞大的 monorepo。
- 适用场景建议:
- 当项目之间有很多共享代码和资源时,monorepo 能使代码共享更简单,提高代码复用率,比较适用。
- 当团队需要频繁进行跨项目协作时,尤其是涉及跨项目更改的情况,monorepo 有助于提高协作效率,可优先考虑。
- 当统一依赖管理对项目至关重要时,monorepo 能提供更好的依赖管理解决方案,适合采用这种管理风格。
三、multirepo
- 特点与优势:理解了 monorepo 的概念后,multirepo 就比较好理解了,即不同项目对应独立的仓库。在这种模式下,每个项目和库都有自己的版本控制历史和依赖关系,具备以下优势:
- 独立版本控制:每个项目和库可独立跟踪版本控制历史,使版本控制更加清晰。
- 更小的代码库规模:每个项目都有自己的代码库,相对来说规模较小,便于管理和克隆操作。
- 更高的项目自治:每个项目和库能依据自身需求选择技术栈和依赖管理策略,项目灵活性更高。
- 缺点:multirepo 的缺点在于代码共享会变得困难一些,不同项目间难以便捷地复用代码。
四、monorepo 与 multirepo 的对比
下面通过一张表格来对比两个多项目代码管理风格的区别:
monorepo | multirepo | |
---|---|---|
开发 | 只需要在一个仓库中开发,编码方便,新成员入门简单 | 仓库体积小,模块划分清晰。 |
复用 | 代码复用高,方便进行代码重构 | 需要多仓库来回切换,无法实现跨项目代码复用 |
工程配置 | 所有项目统一使用相同的工程配置 | 各个项目可能有一套单独标准 |
依赖管理 | 共同依赖可以提升到 root,版本控制更加容易,依赖管理会变得更方便 | 不同的项目会安装相同的依赖,但即便相同的依赖会存在版本不同的情况 |
代码管理 | 代码全在一个仓库,项目太大用 git 管理会存在问题,无法隔离项目代码权限 | 各个团队可以控制代码权限,也几乎不会有项目太大的问题 |
部署 | 有 lerna 工具支持 | 如果多项目存在依赖关系,开发就需要在不同的仓库按照依赖先后顺序去修改版本以及进行部署 |
总之,在考虑管理多个项目时,不能盲目选用 monorepo 风格,而是要基于实际工作场景和需求来确定到底采用哪种管理方式。