大仓实践录:Lerna/NPM/Yarn Workspace 方案组合和性能对比

2023-11-17 11:26:25 浏览数 (1)

单仓和大仓​

仓就是仓库(repository,简称 repo)。通常我们使用多个仓库(简称多仓,multi-repo)来管理项目代码,也就是每个仓库负责一个模块或包的编码、构建、测试和发布,代码规模相对较小,所以也称为小型规模仓库(简称小仓)。而单一(mono)仓库(简称单仓,mono-repo)是指在一个仓库中管理多个模块或包,当代码规模达到一定程度后可称为大型规模仓库(简称大仓),至于这个程度大小并没有明确定义,通常说的大仓可理解为就是单仓。

我们以一个通常的 Node JS 项目为例,简要说明这几种仓库管理方式,如下图:

为便于理解,这里我从软件架构层面引出大仓,但其实仓库管理方式和软件架构并没有直接关系,大仓也并非“银弹”,本文重点在 JS 生态的实践。

当业务系统不复杂时,通常只用一个仓库管理项目,项目为单体架构(Monolithic),依赖和工作流都是统一的。随着业务复杂度的提升,项目的复杂性会巨幅增长,由此导致了一系列问题:比如技术债务越积越多、部署效率/频率低、扩展受限等等。此时就需要业务和模块的拆分,比如从软件架构层面提出了微服务架构(Microservices),而在代码管理上通常会使用多个仓库,每个仓库都独立进行各模块的编码、测试和发版等。这种方式虽然在业务逻辑上解耦了,但却增加了项目的工程管理难度,比如:

  1. 代码和配置很难共享:每个仓库都需要做一些重复的工程化能力配置(如 eslint/test/ci 等)且无法统一维护
  2. 依赖治理复杂:
  • 假设有多个工程依赖 lib,每个工程都会重复安装 lib
  • lib 升级时,所有工程需各自升级,这点很难做到,往往各工程的依赖版本并不一致,由此经常引发一些调试和维护问题
  • 多个工程间互相依赖且同时开发时调试相对困难,如 pkgA 依赖 pkgB,通常需要手动 link pkgB

大仓管理正好解决了这些问题:所有包的依赖统一交由顶层 node_modules,具备统一的工作流,共享基础的库和工程化配置等。

大仓能力和工具链​

为了更好地实现大仓管理,需要配合使用相关的工具。大仓管理工具应该至少具备以下两大能力:

  1. 依赖管理:可管理所有 package 的依赖和彼此之间的关联,并将安装的依赖提升到顶层 node_modules
  2. 更精准的执行和发布控制:能够进行独立或统一的测试、构建和精准发布等

如果没有这两个能力,那大仓就相当于把各个项目用一个目录管理了起来,并没有什么实际用处。在 Node 生态中,主要有 NPM/Yarn 两种包管理器,两者都可以通过开启 Workspace 特性来支持能力 1 并对能力 2 提供部分支持。Lerna 和 Bolt 等工具对能力 2 的支持较好,综合两者在 Github 的活跃度和用量,本文选择 Lerna(主要是 Bolt 我也没用过

0 人点赞