monorepo

618 阅读6分钟

什么是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项目常用:

由Google推出,支持多种语言的项目,并为多种平台构建输出,可以在Linux、macOS和Windows上运行。Uber的服务端使用Go语言开发,就是使用它来实现monorepo的。

由Facebook推出,常见于常用于Android和iOS开发的monorepo项目。Facebook团队就在使用。

由Twitter推出,常见于python项目使用。

JS项目常用:

强调现代全栈Web技术,适用于全栈monorepo项目

由微软推出,主要是微软下的一些团队在使用。

面向JS/TS项目,亚马逊、Paypal等团队在使用。

这是在前端项目体系中使用量最大的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

完结

撒花🌺