前端工程化-monorepo

ObjectKaz Lv4

介绍

大型项目的两种管理方案

当项目规模越来越大的时候,根据分而治之的原则,我们往往会把这些项目拆成众多的子项目。对于前端来说,一个子项目一般就是一个npm包。

现在我们需要使用Git来管理这个大项目,那么我们可以有下面的两种策略:

  1. multirepo:每个npm包分别放在一个Git仓库中(可使用子模块把这些仓库连接起来)
  2. monorepo:所有包放在一个Git仓库中

需要考虑什么

无论采用哪种方案,都需要考虑一些问题:

  1. 这些子项目如果存在相互依赖,应该如何处理(内部依赖互相link)
  2. 这些子项目若涉及到构建,那么构建肯定会有个先后顺序(因为子项目的依赖关系会形成一个拓扑结构)。
  3. 构建的时候,一般会构建所有的子包,对于没有修改的子包也会被执行构建。需要考虑一种策略,防止不必要的构建被执行。(测试等也是同理的)
  4. 发布新版本的时候,如何计算各个子项目的版本

multirepo

对于相互依赖这个问题,一种常规的方法是先发布A包的新版本,然后再升级依赖A的包;在调试环境下,则可以通过npm link来处理。

对于构建顺序的问题,目前得靠人工来指定顺序。

除了上面两个问题,multirepo方案还有难以复用规范化、工作流、构建等基础设施的问题。

monorepo

首先monorepo完全不用考虑基建复用的问题,因为项目都在一个仓库里,规范化、工作流和构建等设施复用起来是非常方便的。

对于相互依赖的问题,现代化的monorepo解决方案,在安装依赖的时候自动进行链接。

对于构建顺序的问题,现代化的monorepo解决方案,在执行脚本时能够根据这些项目的依赖关系进行拓扑排序,从而保证正确的构建流程。

但是,如果项目规模巨大,monorepo会导致git clone 和安装依赖的时间很长。

monorepo 解决方案

lerna

|功能特性|依赖管理|拓扑序工作流|包版本管理|发布|
|----|----|----|----|
|lerna|基于npm,支持yarn workspace|√|√|√|

Lerna是一款经典的 monorepo解决方案。官网

新版的Lerna交由Nrwl来管理,在原本的基础上增加了:

  • 分布式任务执行(基于nx cloud):可以将任务分配到多台机器上进行构建
  • 计算缓存:可以根据命令的输入文件来判断命令是否需要执行,避免不必要的命令执行。

常用操作

  1. 初始化lerna仓库:
1
npm init lerna
  1. 创建子项目(默认创建在 ./packages
1
lerna create <package-name> [dest]
  1. 安装依赖
1
lerna add <package-name> [--scope=范围]
  1. 查看所有包
1
lerna list
  1. 导入本地已存在的包
1
lerna import 目录
  1. 根据项目的拓扑结构执行命令
1
2
lerna run 命令名
lerna exec [--scope 作用域] -- 命令
  1. 清理 node_modules
1
lerna clean
  1. 在发布前,列出需要更新的包

lerna会通过git来对比两个tag之间,各个包的修改记录。

1
lerna changed
  1. 更新包版本并发布(只会发布修改过的包)
1
lerna publish

在初始化的时候,版本管理模式有下面两种,不同的模式会有不同的操作:

  • fixed 固定模式,所有包采用统一的版本号
  • independant 独立模式,每个包都采用不同的版本号,发布时每个包都需要独立指定版本号

注意:

  • 约定好发布分支,不要使用其他分支进行发布(lerna不会检测,所以使用不同的分支发布会出现重复发布的情况)
  • 如果发布失败,可以使用 lerna publish from-git 根据当前的 git tag 重新发布版本

Pnpm

|功能特性|依赖管理|拓扑序工作流|包版本管理|发布|
|----|----|----|----|
|lerna|√|√|×,需要借助changesets或者rush|√|

pnpm是一款新的包管理工具,它能够很好地利用磁盘缓存来减少空间占用,同时通过特殊的node_modules管理策略来防止幽灵依赖。

pnpm同时支持 workspace 模式,以monorepo的方式管理项目。

Yarn

|功能特性|依赖管理|拓扑序工作流|包版本管理|发布|
|----|----|----|----|
|lerna|√|√|×|√|

yarn 也支持 workspace 模式管理项目,但是会将所有依赖提升到根node_modules,加剧了幽灵依赖的问题。

参考

  1. 现代前端工程为什么越来越离不开 Monorepo?:https://juejin.cn/post/6944877410827370504
  • 标题: 前端工程化-monorepo
  • 作者: ObjectKaz
  • 创建于: 2022-07-06 02:23:11
  • 更新于: 2022-07-23 08:31:27
  • 链接: https://www.objectkaz.cn/fc43243ca6e0.html
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。