什么是monorepo?
目录结构:
ts
.
├── lerna.json
├── package.json
└── packages/ # 这里将存放所有子 repo 目录
├── project_1/
│ ├── index.js
│ ├── node_modules/
│ └── package.json
├── project_2/
│ ├── index.js
│ ├── node_module/
│ └── package.json
...
优点:
- 代码复用:在维护多个项目时,一些逻辑可能会被复用,比如基础的封装组件、工具函数。在 monorepo 中,由于所有的项目在一个仓库中,我们复用非常方便,修改一次,就可以在其他依赖的项目中得到更新。
- 项目基建成本的降低:所有项目复用一套标准的工具和规范,如果有新的项目接入,可以直接复用已有的基建流程,然后将基建统一维护,维护成本大大降低。
缺点:
- 仓库体积较大:由于monorepo将所有包和项目都放在一个仓库中,随着项目的增长,仓库的体积会变得越来越大。这可能导致克隆、拉取和推送等Git操作变得缓慢,影响开发效率。
- 构建和测试时间较长:在monorepo中,所有包和项目共享一个构建和测试系统。随着项目数量的增加,构建和测试所需的时间可能会变得较长,影响开发和部署速度。
- 跨团队协作复杂度较高:在monorepo中,多个团队需要在同一个仓库中协作。这可能导致权限管理、代码审查和合并冲突等问题变得更加复杂。
聊聊我们使用过的 monorepo 工具,如 Lerna、Yarn Workspaces
Lerna 和 Yarn Workspaces 在很大程度上功能是互补的,虽然有一定的重叠,但关注点和侧重点并不完全相同。 在我们实际的项目中,可以单独使用,也可以结合使用。
-
Lerna
- Lerna 是一个用于管理具有多个包的 JS 项目的工具。它主要关注于包之间的依赖关系管理、版本管理和发布。
- Lerna可以自动识别包之间的依赖关系,并在执行命令时按照依赖顺序执行。但Lerna不会自动将所有包的依赖安装到根目录的
node_modules
中,每个包仍然有自己的node_modules
。 - Lerna可以与多种包管理器(如npm、Yarn等)一起使用,具有较好的兼容性。
-
Yarn Workspaces
- Yarn Workspaces是Yarn包管理器的一个功能,主要关注于提高多包项目的依赖安装效率,通过将所有包的依赖安装到项目根目录的
node_modules
中,避免了重复安装相同依赖。 - Yarn Workspaces本身不提供依赖关系管理功能。
- Yarn Workspaces是Yarn的一个功能,只能在Yarn环境下使用。
- Yarn Workspaces是Yarn包管理器的一个功能,主要关注于提高多包项目的依赖安装效率,通过将所有包的依赖安装到项目根目录的
在monorepo项目中,如何配置CI/CD流程?
在网上看到的一些参考回答,大致是需要自己写脚本,具体细节并没有实现过,所以不知道。
- 使用增量构建和测试 :为了提高CI/CD流程的效率,可以使用增量构建和测试策略。只针对受更改影响的包进行构建和测试,而不是每次都构建和测试整个仓库。可以使用一些工具(如
lerna
的lerna changed
命令)来检测哪些包发生了更改。 - 并行构建和测试:在CI/CD流程中,可以使用并行构建和测试来提高效率。许多CI/CD服务(如Jenkins、GitLab CI、GitHub Actions等)支持并行执行任务。通过将不同包的构建和测试任务分配给不同的执行器,可以大大减少总体构建和测试时间。
- 使用构建缓存:为了减少构建时间,可以使用CI/CD服务中的构建缓存功能。将常用的依赖和构建产物缓存起来,以便在后续构建中重用。这可以大大减少依赖安装和构建所需的时间。
- 配置部署策略 :在monorepo项目中,需要根据不同包的需求配置部署策略。例如,可以为每个包配置独立的部署任务,以便在包发生更改时触发部署。此外,可以使用一些自动化部署工具(如
lerna publish
)来简化部署过程。 - 优化CI/CD配置:在配置CI/CD流程时,尽量遵循DRY(Don't Repeat Yourself)原则,避免重复的配置。可以使用一些模板和共享配置来简化CI/CD配置。此外,定期审查和优化CI/CD配置,以确保流程的高效和稳定。
- 监控和报警:为了确保CI/CD流程的稳定性,可以配置一些监控和报警策略。例如,当构建失败或部署出现问题时,可以发送通知给相关人员。这有助于及时发现和解决问题,确保项目的稳定性。
在实际项目中使用 monorepo 遇到的问题和解决方案。
-
仓库体积过大:随着项目的增长,monorepo仓库的体积可能会变得很大,导致克隆、拉取和推送等Git操作变得缓慢。
解决方案:可以使用Git的
shallow clone
功能来克隆仓库的部分历史记录,以减少克隆时间。此外,定期清理不再使用的分支、合并历史记录以及优化存储库中的大文件(如使用git-lfs
)也有助于减小仓库体积。 -
构建和测试时间较长:随着项目数量的增加,构建和测试所需的时间可能会变得较长。
解决方案:可以使用增量构建和测试策略,只构建和测试受更改影响的包。此外,可以使用并行构建和测试来提高效率。还可以考虑使用CI/CD服务中的构建缓存功能,以减少构建时间。
-
跨团队协作复杂度较高:在monorepo中,多个团队需要在同一个仓库中协作,可能导致权限管理、代码审查和合并冲突等问题变得更加复杂。
解决方案:可以使用代码所有权和代码审查策略来确保每个团队对其负责的代码进行管理。此外,使用分支策略(如Git Flow或GitHub Flow)以及定期同步主分支可以减少合并冲突。
-
依赖管理复杂度较高:在monorepo中,不同项目可能会依赖不同版本的相同依赖库,导致依赖管理变得复杂。
解决方案:尽量确保所有包使用相同版本的共享依赖。可以在项目根目录的
package.json
中指定共享依赖的版本,然后在各个包的package.json
中引用这些依赖。使用monorepo管理工具(如Lerna、Yarn Workspaces等)也有助于简化依赖管理。