初识monorepo

avatar
web前端

什么是 monorepo

概念

monorepo 是一种项目代码管理方式,指单个仓库中管理多个项目,有助于简化代码共享、版本控制、构建和部署等方面的复杂性,并提供更好的可重用性和协作性

演变

  • monolith(单仓库单应用)

单仓库单应用,一个仓库维护着项目代码,随着业务迭代,项目越来越复杂越来越庞大,构建效率也会越来越低

  • multirepo(多仓库多应用)

多仓库多应用,微前端就是这种形式,每个模块都可以独立编码、测试、上线,代码管理变得简化,构建效率也有很大提升

  • monorepo(单仓库多应用)

单仓库多应用,多个项目集成到一个仓库下,共享工程配置,同时又快捷地共享模块代码

14ba61eb924c4411bc4ff102f8f3f530~tplv-k3u1fbpfcp-jj-mark-3024-0-0-0-q75.awebp.webp

使用 monorepo 结构的优劣势

9ef91440-8931-432b-be4e-1dd0cd643ea7 .jpg 中大型项目,多个模块之间关联性较强,更适合用 monorepo 方式管理代码

相关基建

  • 依赖管理

基于 workspace 实现依赖管理,首先公共依赖提升,节省空间和下载速度,其次依赖实时更新模块之间的调试更加方便

/* 配置 private */
{
  "name": "pnpm-mono",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "private": true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
}
// pnpm-workspace.yaml 文件配置
packages:
  - packages/*

packages 目录下创建 UI、components 两个应用 image.png

// components 中安装依赖 ui
pnpm --filter @pnpmpkg/components add @pnpmpkg/ui -S
/* packages.json 中会添加相关依赖 */
"dependencies": {
  "@pnpmpkg/ui": "workspace:^"
}
  • 版本管理(eg:changeset)

自动发版、更新版本号,更新方式有独立更新、同步更新

/* 初始化 */
npx changeset init
/* 记录需要更新的包和版本号 */
npx changeset
/* 更新对应包的版本号 */
npx changeset version
  • 打包构建(eg:pnpm)

对接 CICD,控制编排构建顺序,发布应用

/* --parallel 并行打包  -r 打包所有 package */
pnpm run --parallel -r build
/* 发布 package */
pnpm publish
  • 增量构建 & 缓存(eg:turborepo)

使用缓存技术保存上次构建结果,包括编译后的代码、测试结果等,如果检测到某个包或任务自上次构建以来没有变化(基于文件指纹比较),跳过这些任务的执行,并直接使用缓存中的结果,只有自上次成功构建以来发生变化的部分才会被重新构建

// 安装 turborepo
pnpm add turbo -D
// 配置 turbo.json 文件
{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "outputs": ["dist/**"]
    },
    "lint": {}
  }
}
// 执行编译
npx turbo run build

Snipaste_2024-07-29_15-42-56.png

Snipaste_2024-07-29_15-43-51.png

实现方案

  • 轻量化方案:npm、yarn、pnpm

对于依赖管理相关,pnpm 有自己独有的优势,比如幽灵依赖、下载速度、磁盘空间等,所以依赖管理的最优解还是 pnpm

  • 构建性方案:pnpm + lerna + Nx、 pnpm + changeset + Turborepo

1、lerna 和 Nx 现在归一个公司管理,lerna 集成 Nx 更方便,二者结合打包速度更快( Nx 避免还原每个文件,而是检查实际需要从缓存中还原哪些文件,从而减少 I/O 负载, Turborepo 每次都会从缓存中完全恢复文件)

2、Turborepo 借鉴了 Nx 的许多想法,新出来的框架,社区贡献相对较少

  • 方案建议

中型项目全功能轻量级方案:pnpm + changeset + Turborepo

中大型项目构建速度最优化方案:pnpm + lerna + Nx