monorepo 初学者想知道的都在这了

1,585 阅读5分钟

个人学习 monorepo,了解基础概念,作用,基本结构,架构等内容。

简介

monorepo = mono(单个)和 repo(存储库)

monorepo 是一个包含更小项目的项目,每个项目可以是单个应用程序或可重用包中的任何内容,可以将其较小的项目组合成多个项目。

作用

一般作用于任何具有多个应用程序和一组共享(内部)包的代码库、大规模代码库。

  • 在大规模代码库中具有共享包,依赖实时更新,无需手动更新、出错。

  • 提升跨代码库的协作,单一存储库,提高不同团队可访问性,重构迭代代码

结构

monorepo 两个重要概念:应用

应用

- apps/
--- app-one
--- app-two
  • 一个 monorepo 可以包含多个应用,而每个应用程序都可以访问共享的包。
  • 应用通常不相互依赖,而只是选择加入。如果包相互依赖,通过 monorepo 管道工具来进行构建管理。

TurborepoLernaNx使我们在没发布 NPM 之前,能够构建库和应用程序,使得在构建相互依赖的应用时,可以更快地进行本地迭代。

还提供高级命令来优化多个包的管理。可以遍历所有包,对每个包运行一系列操作(例如 linting、测试和构建)。

  • 应用也可以选择使用其 UI 组件、功能和配置在其内部实现。但是,如果应用决定使用包作为依赖项,则必须在其package.json文件中定义相关包。
{
  "dependencies": {
    "ui": "*",
    "utilities": "*",
    "eslint-config": "*"
  },
}
  • 应用本身不感知作为 monorepo 中的存储库,只是定义依赖关系。其决定依赖项来自 monorepo(默认)或来自注册表(例如 npm 注册表)。
  • 应用程序可以在不属于 monorepo 的情况下使用。唯一的要求是它的所有依赖项都发布在像 npm 这样的注册表上。(因为当用作独立应用程序时,不再有具有共享依赖项的 monorepo)

  • 包只是一个文件夹,可以是任何内容。如 UI 组件、功能、配置(例如 ESLint、TypeScript)
- packages/
--- ui
--- utilities
--- eslint-config
--- ts-config
  • 一个包可以是另一个包的依赖项。

例如,UI 包可能依赖 utilities 包中的功能。UI 和 utilities 以使用来自其他** -config*包的配置。

工作区

当 monorepo 由多个一起工作的应用程序/包组成时,需要工作区创建一个文件夹结构,让应用可以在其中使用作为依赖项。

常见yarn 工作空间npm 工作区pnpm 工作区

在顶级package.json文件中定义:

"workspaces": [
  "packages/*",
  "apps/*"
],

appspackages中带有package.json文件的每个文件夹都会被拾取。如果在apps的应用想要包含来自packages的包,只需使用包的package.json文件中的name属性作为自己 package.json 文件中的依赖

我们需新增应用到 monorepo 工作区时,一共三步:

  1. 将应用 clone 到对应 apps 文件夹下。
  2. 安装新增应用的所有新依赖项。
  • apps 中的新增应用需要安装其所有依赖项——包括它们定义为依赖项的包。
  • 应用与包之间可能存在新的依赖关系,在package.json文件中指定。
"dependencies": {
  "@bigstair/core": "*",
  "@bigstair/map": "*",
  ...
}
  1. 新增应用即可使用相关依赖。

因此,任何 JavaScript 或 TypeScript 应用都可以通过工作区方式在 apps 文件夹中继续创建新的应用程序,并将packages定义为依赖项,使用工作区中的共享组件。

monorepo 顶层 package.json 文件定义了工作空间以及可以在每个嵌套工作空间中使用的全局依赖项。相反,嵌套的package.json文件只定义了实际项目中需要的依赖项。

文档

monorepos 项目应用一般带有 documentation 文档应用,来对一组共享包进行记录、使用或API。如使用 Storybook 来记录包的所有 UI 组件。

如果共享包不是 UI 组件,您可能需要其他工具来记录、使用或 API。

Git

monorepo 通过 git 存储库时,一般会将应用分成多个 Git 存储库(除了 ducument 文档)。使用顶级的 .gitignore 文件,忽略应用中其他应用,应存储任何共享包及 monorepo 配置。

相关的应用有它们专用的 Git 存储库

通过这种方式,当将所有嵌套工作空间克隆到 monorepo 或作为独立应用程序时,它们只能拉取使用最近的代码。因此需考虑版本控制来绕过这个问题。

也就是在工作区 package.json 文件下的依赖指定依赖包版本

"dependencies": {
  "@bigstair/core": "1.0.0",
  "@bigstair/map": "1.0.0",
  ...
}

这就需要将相关版本的依赖包发布到 NPM 上进行持续集成。

架构

Monorepos 变得越来越流行,因为其允许将源代码拆分为多个应用程序/包,同时仍然能够在一个地方管理所有内容,其流行的最小的 monorepo 架构如下:

  1. 工作区(Workspaces):yarn / npm / pnpm 工作空间。
  2. 管理工具:Turborepo / Lerna / Nx。

允许以更方便的方式在全球范围内运行脚本,在 monorepo 中编排脚本,或在本地/远程缓存执行的脚本,优化多个包的管理及操作。

  1. 存储库:Git 存储库工具。
  2. 版本控制工具:Changesets。

用于为 monorepo 创建变更日志、版本和发布。它是monorepo 空间中语义释放的替代方案。

参考

如果对您有点帮助~~可以点赞收藏 🍉