什么是monorepo
代码管理发展历程
单体应用架构Monolith
特点
一个代码仓库,一个npm包
所有的功能和模块打包在一起,形成一个单一的代码库和部署单元。缺点
- 难以实现部分更新和独立扩展的灵活性
- 高度耦合,代码臃肿,不好维护
- 代码量大了后,调试、构建效率显著下降
- 无法跨项目复用
多仓模块管理Multirepo(Polyrepo)
特点
多个代码仓库,多个npm包
每个代码仓库对应一个npm包
将不同的功能模块、组件或服务等分别存放在独立的仓库中,可以单独进行版本控制、构建、部署和发布,使得不同的团队或开发者可以独立地开发、测试和维护各自的模块,更容易实现并行开发和团队协作。
相对于单体应用架构
- 拆分之后,模块组件独立开发调试,独立部署,代码复用、维护性提升
- 多个团队维护的项目,拆分之后,团队协作更方便,权限控制更精确
缺点
- 包之间的依赖管理:
- 开发调试:npm包(修改->发布->安装成本高),调试麻烦(npm link)
- 依赖图分析:没有可视化依赖关系,不容易理解项目关系结构
- 命令执行:如果运行多个项目的命令(如调试、构建),需要手动执行,比较麻烦
- 版本更新、自动 tag、发布:发布时候需要手动到多个项目下操作;依赖版本管理,依赖版本同步升级管理麻烦
- 项目基建:构建配置不复用,不好管理;脚手架升级,新老项目规范很难保证统一
- 共同引用的版本问题,容易导致重复安装相同依赖的多个版本
- 串行构建,修改模块体量大时,发布成本急剧上升
单仓多模块管理Monorepo
特点
一个仓库,多个npm包
单仓多npm包当然不是简单地把多个模块放到一个git仓库,还需要支持更多能力。
如果一个项目涉及多个模块,多个模块间有依赖关系,适合用monorepo。
如果模块之间比较独立,通常更推荐用multirepo,但如果
- 希望用相同的构建配置或者代码约束
- 模块间有很多共享代码
也可以酌情使用monorepo,但要权衡利弊,因为这时候monorepo也可能带来不方便的地方:
- 开发者可能只关注某个模块,其他模块显得冗余,带来搜索和更新时候的心智负担
- 冗余模块会带来额外的磁盘存储
- 冗余模块会带来下载项目的额外带宽
monorepo解决的问题
lerna 还是 pnpm + changesets?monorepo 工具核心就看这三个功能
monorepo主要解决3个核心问题
- 依赖管理:如果使用multirepo,一个包更新后,需要把这个包发布到npm,依赖它的其他模块才能感知到。当然也可以通过npm link实现,但是项目多的时候不好管理,而且每次npm install之后npm link会失效,这都给本地调试带来麻烦。
- 命令执行:如果模块间有依赖关系,执行命令时候可能要到多个模块目录执行命令,而且还涉及到命令执行顺序,这给执行命令的场景(如build)带来麻烦
- 发布:发布项目时候可能涉及多个模块改动,并且涉及版本更新,如果都是手动到各自模块目录去处理,会非常麻烦
monorepo能力
核心3个能力lerna 还是 pnpm + changesets?monorepo 工具核心就看这三个功能
- 依赖管理:依赖的包更新后,不需要走npm发包流程,本地调试更方便
- 命令执行:可以按照依赖的关系,按顺序批量执行命令(如build构建)
- 发布管理:(版本更新、自动 tag、changelog)发布时候可以①在主目录管理涉及改动的包的更新记录,②被依赖的包更新后,依赖的包可以自动更新依赖包版本,并更新自己的patch版本。
当然完善的monorepo也支持更多的能力:
- 依赖图可视化
- 代码共享
- 构建缓存、本地命令缓存
- 分布式任务执行
- ……
monorepo实践
概述
基于上面提到的monorepo的核心能力有3个,依赖管理,命令执行,发布。
其中依赖管理能力,目前包管理管局已经支持(包括npm、yarn、pnpm最新版本已经可以支持多包项目的依赖管理,自动link)。
命令执行和发布能力有很多开源库可以支持。
包管理npm/yarn/pnpm
受lerna的启发,目前npm、yarn、pnpm包管理工具内置了对多包管理的支持。
lerna
lerna目前由Nx团队负责维护. Lerna 主流应用在处理版本、构建工作流以及发布包等方面都比较优秀,既兼顾版本管理,还支持全量发布和单独发布等功能。在前端领域,它是最早出现也是相当长一段时间 monorepo 方案的事实标准,具有统治地位,很多后来的工具的概念或者 workspaces 结构都借鉴了 lerna,是 lerna 的延续。在业界实践中,比较多的时间上,都是采用 Yarn 配合 lerna 组合完整的实现了 Monorepo 中项目的包管理、更新到发布的全流程。 实际上,自动npm自动link是lerna 先实现的,它提供了 lerna bootstrap 来完成这种 link,只不过后来 npm、yarn、pnpm 都内置了这个功能,叫做 workspace。就不再需要 lerna 这个 bootstrap 的命令了。lerna 还是 pnpm + changesets?monorepo 工具核心就看这三个功能综合看下来,lerna 在功能上和 pnpm workspace + changesets 没啥大的区别,但是在性能上更好点。lerna支持命令缓存、分布式执行任务等性能的优化。 lerna可以指定 npmClient 为 pnpm,即把依赖管理能力交给pnpm,自己负责命令执行和发布。
Nx Monorepo,大型前端项目管理模式实践
定位上是 Smart, Fast and Extensible build system,出现得比较早,发展了挺久,功能特别多,基本上 cover 了各种应用场景,文档也比较详细,是现在几个 Monorepo 工具里比较接近完整的解决方案和框架的。 最近的话他们也接手了 lerna 的维护,不过给 lerna 加的东西都是围绕 nx 而来。 推荐导读:https://nx.dev/turborepo
简介
turborepo由vercel提出 TurboRepo 是构建Javascript,Typescript的monorepo高性能构建系统,Turborepo抽象出所有烦人的配置、脚本和工具,减少项目配置的复杂性,可以让我们专注于业务的开发 我们通常在构建monorepo 时需要搭配适当的工具来扩展 monorepo,Turborepo利用先进的构建技术和思想来加速开发,构建了无需配置复杂的工作,只需要我们通过脚本和工具,即可快速搭建您的Monorepo TurboRepo 支持使用Yarn Npm Pnpm。核心功能
- 包管理:支持npm,yarn,pnpm
- 运行任务(自动识别项目中的 dev, build 命令,并全量运行)
- 仅运行某个单独的包
- 默认使用缓存
注意,目前turborepo不支持版本控制,官方推荐Changesets。
参考文章
lerna 还是 pnpm + changesets?monorepo 工具核心就看这三个功能