什么是monorepo

代码管理发展历程

单体应用架构Monolith

特点

一个代码仓库,一个npm包

所有的功能和模块打包在一起,形成一个单一的代码库和部署单元。

缺点

  1. 难以实现部分更新和独立扩展的灵活性
  2. 高度耦合,代码臃肿,不好维护
  3. 代码量大了后,调试、构建效率显著下降
  4. 无法跨项目复用

多仓模块管理Multirepo(Polyrepo

特点

多个代码仓库,多个npm包

每个代码仓库对应一个npm包

将不同的功能模块、组件或服务等分别存放在独立的仓库中,可以单独进行版本控制、构建、部署和发布,使得不同的团队或开发者可以独立地开发、测试和维护各自的模块,更容易实现并行开发和团队协作。

相对于单体应用架构

  1. 拆分之后,模块组件独立开发调试,独立部署,代码复用、维护性提升
  2. 多个团队维护的项目,拆分之后,团队协作更方便,权限控制更精确

缺点

  • 包之间的依赖管理:
    • 开发调试:npm包(修改->发布->安装成本高),调试麻烦(npm link)
    • 依赖图分析:没有可视化依赖关系,不容易理解项目关系结构
  • 命令执行:如果运行多个项目的命令(如调试、构建),需要手动执行,比较麻烦
  • 版本更新、自动 tag、发布:发布时候需要手动到多个项目下操作;依赖版本管理,依赖版本同步升级管理麻烦
  • 项目基建:构建配置不复用,不好管理;脚手架升级,新老项目规范很难保证统一
  • 共同引用的版本问题,容易导致重复安装相同依赖的多个版本
  • 串行构建,修改模块体量大时,发布成本急剧上升

单仓多模块管理Monorepo

特点

一个仓库,多个npm包

单仓多npm包当然不是简单地把多个模块放到一个git仓库,还需要支持更多能力。

如果一个项目涉及多个模块,多个模块间有依赖关系,适合用monorepo。

如果模块之间比较独立,通常更推荐用multirepo,但如果

  1. 希望用相同的构建配置或者代码约束
  2. 模块间有很多共享代码

也可以酌情使用monorepo,但要权衡利弊,因为这时候monorepo也可能带来不方便的地方:

  1. 开发者可能只关注某个模块,其他模块显得冗余,带来搜索和更新时候的心智负担
  2. 冗余模块会带来额外的磁盘存储
  3. 冗余模块会带来下载项目的额外带宽

monorepo解决的问题

lerna 还是 pnpm + changesets?monorepo 工具核心就看这三个功能

monorepo主要解决3个核心问题

  1. 依赖管理:如果使用multirepo,一个包更新后,需要把这个包发布到npm,依赖它的其他模块才能感知到。当然也可以通过npm link实现,但是项目多的时候不好管理,而且每次npm install之后npm link会失效,这都给本地调试带来麻烦。
  2. 命令执行:如果模块间有依赖关系,执行命令时候可能要到多个模块目录执行命令,而且还涉及到命令执行顺序,这给执行命令的场景(如build)带来麻烦
  3. 发布:发布项目时候可能涉及多个模块改动,并且涉及版本更新,如果都是手动到各自模块目录去处理,会非常麻烦

monorepo能力

核心3个能力lerna 还是 pnpm + changesets?monorepo 工具核心就看这三个功能

  1. 依赖管理:依赖的包更新后,不需要走npm发包流程,本地调试更方便
  2. 命令执行:可以按照依赖的关系,按顺序批量执行命令(如build构建)
  3. 发布管理:(版本更新、自动 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。

参考文章

带你了解更全面的 Monorepo - 优劣、踩坑、选型

Monorepo,大型前端项目管理模式实践

lerna 还是 pnpm + changesets?monorepo 工具核心就看这三个功能

Hello Monorepo

带你了解并实践monorepo和pnpm,绝对干货!熬夜总结!

初识Monorepo

🚀Turborepo:发布当月就激增 3.8k Star,这款超神的新兴 Monorepo 方案,你不打算尝试下吗?