什么是Monorepo?
Monorepo 是一种将多个项目代码存储在一个仓库里的软件开发策略。mono是monolithic的缩写,这个词的中文翻译是单块的、庞大的(名词形式monolith翻译为单块巨石)据说源于希腊语 μόνος;repo就是指我们常见到的repository,指代码仓库。直译过来是单块巨石般的代码仓库,这个命名十分生动形象。
据说Google的所有代码都在一个仓库当中,对这件事情感兴趣请戳这里。
对比Multirepo?
Multirepo与Monorepo相对应,有单仓多包的策略,自然就有多仓多包的策略,这也是目前我们开发当中更常见、更传统的策略。Multirepo即multiple repository,顾名思义,这种策略提倡把项目按模块分为多个代码仓库。
Multirepo与Monorepo对应着 “分” 与 “合” 的两种思想,没有绝对的利与弊,适合自己场景,能够高效开发协作就是好的策略。
无图无真相👇
这两种方式各自有什么利弊呢?我们从新创建一个项目的过程来横向对比下。
Multirepo
先从我们更常使用的Multirepo开始。当有一个新的项目要开始开发时,我会:
这个过程上手很方便,但也会伴有一些大家可能会遇到的困惑:
- 有一些代码,可能是从另一个项目当中复制而来,发现有一些改进空间时,要修改多份,带来一些维护成本;
- 有一些通用代码,可能来自于共用npm包,需要安装,npm包中有bug或者不满足需求时,把问题是反馈给npm开发的同学等待其修改,会有一些沟通成本;或者npm包自己有权限自己来修改,这时候可能需要做一些开发之外的npm link调试,然后再发布npm包等等的工作,也有一定成本;
- 依赖的NPM包以及或者一些开发工具与其他项目有很大一部分是相同的,但独立不同仓库会有许多NPM包重复安装多次,以及一些开发工具、构建、部署的配置也都是相同的配置复写了几次;
- 项目比较多时,有共用的npm包更新,想在项目升级,需要重复操作多次等。
从这个过程中,进行总结,可以发现:
-
✅:
- 灵活:每个repo可以灵活选择开发工具和环境配置等
- 权限控制:git仓库天然带有的权限控制
- 安全:发布不会对其他项目产生影响
-
❌:
- 代码/配置复用上,可能会有的复制行为会带来维护一定成本
- 项目基建上,多个项目时,大量安装重复的npm包及重复处理多个相同的构建、部署、辅助开发工具配置
- 开发调试上,跨项目引用调试,可能要打开多个IDE窗口切换,进行npm link等操作也带来一定成本
- 版本管控上,想要升级共用NPM包也要重复处理多次
还有其他优缺点欢迎补充👏。
Monorepo
使用Monorepo的策略,要开始开发时,我会:
这个过程上手也很便捷,也会有一些困惑点产生:
- 把许多项目的代码都放在一个仓库,仓库体积不是会越来越庞大?(如其名,monolith单块巨石🙃️)
- 万一改动的时候没注意改了其他项目,发布的时候可能影响了其他项目。。。
- 这么多项目在一个仓库,没办法逐个做权限管控了
从这个过程中,可以发现:
-
✅:
-
更方便的复用和共享:
- 辅助开发工具、构建打包、部署的配置可以共用一份
- 一些需要共用的npm包等依赖只需要安装一份,无需重复安装
-
开发调试便捷:引用同仓库内的复用部分,可以规避npm包形式复用带来的调试、修改、安装成本
-
统一的工作流及基建,减少一定的维护成本
-
升级公用的npm包时也更加方便,只需操作一遍
-
-
❌
- 项目很多时,仓库体积会比较大
- 项目之间没有独立的权限控制
- 相应项目中有通用代码也是没有办法做版本控制的
还有其他优缺点欢迎补充👏。
为什么要使用?
通过上述对比,“分”与“合”的策略是各有千秋的,没有绝对的好坏,只要根据自己的场景诉求进行选择即可,最终能够高效开发就是好的。
这里主要是介绍下Monorepo的策略更加适合的场景。
当需要维护多个项目,多个项目之间有依赖,这些项目共用相同的基础设施(组件、构建工具、lint)的时候,使用monorepo 会带来很多好处。
- 使用 monorepo 能减少依赖安装时间,同时也减少安装重复依赖的空间占用。
- 项目之间依赖调试非常方便,都在一个代码库下。
- 统一的工作流,几个项目共用基础设施,不用重复配置。
- 统一的研发规范等等。
怎么使用?
monorepo的策略也有10年+历史了,在这个过程中也已经有许多管理工具出现。
开源管理工具
这里列举一些常见的开源管理工具:
非JS项目常用:
- Bazel:bazel.build/
由Google推出,支持多种语言的项目,并为多种平台构建输出,可以在Linux、macOS和Windows上运行。Uber的服务端使用Go语言开发,就是使用它来实现monorepo的。
- Buck: buck.build/
由Facebook推出,常见于常用于Android和iOS开发的monorepo项目。Facebook团队就在使用。
- Pants: github.com/pantsbuild/…
由Twitter推出,常见于python项目使用。
JS项目常用:
- NX:nx.dev/
强调现代全栈Web技术,适用于全栈monorepo项目
- Rush: rushjs.io/
由微软推出,主要是微软下的一些团队在使用。
- Turborepo: turborepo.org/
面向JS/TS项目,亚马逊、Paypal等团队在使用。
-
Lerna + yarn workspaces:
这是在前端项目体系中使用量最大的monorepo项目管理方式。babel、vue、create-react-app等我们使用频率很高的的库/框架都是使用它来管理项目的。常见的使用方式是yarn workspaces主要处理依赖管理,lerna处理发布管理。关于他们俩的关系,yarn workspaces主要做为底层支持,lerna是更上层的应用。在yarn官网也有叙述:
Yarn Workspaces vs Lerna
Despite the appearances, the Yarn workspaces and Lerna don't compete. In fact, Lerna will use Yarn's workspaces if possible. In a sense, you can see Lerna as a high-level layer on top of the low-level Yarn implementation.
在前端领域的数据统计👇(数据来源戳这里):
从使用量来看:
从关注度来看:
这个调研的方向主要是是否愿意持续学习关注。
项目目录:
project
|--- node_modules
|--- packages
|--- project1
|--- package.json
|--- src
|--- project2
|--- package.json
|--- src
|--- .gitignore
|--- lerna.json
|--- README.md
|--- package.json
完结
撒花🌺