Monorepo 单体式仓库
# 是什么
Monorepo 它代表"单一代码仓库"(Monolithic Repository)是一种项目代码管理方式,指单个仓库中管理多个项目,有助于简化代码共享、版本控制、构建和部署等方面的复杂性,并提供更好的可重用性和协作性。
# 为什么会出现
随着时间的推移,软件项目变得更加复杂,且对共享代码与复用逻辑的需求越来越强烈。这带来了对模块化的需求,旨在减少重复代码,实现更高效的协作与集成。
这种方法已经被很多大型公司广泛使用,如 Google、Facebook 和 Microsoft 等。
# Monorepo 目录结构
.
├── .git
├── packages
│ ├── package-1 # 子包 1
│ │ ├── src
│ │ │ └── index.js
│ │ └── package.json
│ └── package-2 # 子包 2
│ ├── src
│ │ └── index.js
│ └── package.json
└── package.json
# Monorepo 与 Multirepo 比较
- 组织结构: Monorepo 将所有相关项目放在单个仓库中,Multirepo 则是为每个项目分配不同的仓库。
- 项目独立性: Monorepo 可能需要更多的协作和协调,Multirepo 则可能更注重项目或团队的独立性。
- 工具链复杂性: Monorepo 可能需要更先进的工具支持,但简化了共享和依赖管理,Multirepo 则在此方面可能更加繁琐。
# Monorepo 管理工具
# pnpm 管理 Monorepo
自带轻量的 Monorepo 的解决方案。
# 全局安装 pnpm
npm install -g pnpm
# 初始化项目
首先创建一个新的目录作为 Monorepo 的根目录,并在其中初始化 git 和 pnpm。
# 创建项目文件夹
mkdir my-monorepo && cd my-monorepo
# 根目录创建 package.json
pnpm init
# 创建两个子包
mkdir packages
mkdir packages/package-a && mkdir packages/package-b
# 初始化子包的 package.json
cd packages/package-a && pnpm init
cd ../package-b && pnpm init
# 最后再给每个子包创建一个 src/index.js
现在你已经有了两个子包:package-a
和 package-b
。
管理私有包:如果你不希望某个包被发布,确保 package.json
中设置 "private": true
。
# 指定工作区
在 Monorepo 根目录中创建 pnpm-workspace.yaml
文件,指定工作区的位置。
packages:
- 'packages/*'
最终目录结构如下:
.
├── .git
├── packages
│ ├── package-a # 子包 a
│ │ ├── src
│ │ │ └── index.js
│ │ └── package.json
│ └── package-b # 子包 b
│ ├── src
│ │ └── index.js
│ └── package.json
├── package.json
└── pnpm-workspace.yaml
# 依赖管理
在 Monorepo 项目中,依赖分为两种:
- 共有依赖: 在主包根目录下安装的依赖,会被所有子包继承。
- 子包依赖: 在子包中安装的依赖,只会在当前子包中生效。
# 共有依赖
设置 TS、ESLint 等共享配置。
pnpm add -w -D typescript eslint
-w
表示安装到工作空间(即根目录)-D
表示安装开发依赖
# 子包依赖
pnpm --filter package-a add lodash # 可以简写为 -F
-F
表示安装到指定子包
# 包之间的依赖
还可以将工作区中的一个子包作为依赖安装到另一个指定的子包中,例如:安装 package-a
子包到 package-b
子包中:
pnpm -F package-b add package-a
执行完后,package-b
子包的 package.json 中会添加 package-a
子包的依赖,如下:
{
"name": "package-b",
"version": "1.0.0",
"dependencies": {
"package-a": "workspace:^"
}
}
workspace:^
表示安装的是工作空间中的 package-a
子包,依赖的子包版本相关值还有 workspace:*
, workspace:~
。资料参考: pnpm - 工作空间(Workspace)。
在打包或者发布后会被转化为:
{
"dependencies": {
"package-a": "^1.0.0"
}
}
# 总结
Monorepo 是软件开发实践中的一种趋势,其根据项目需求和开发团队规模逐渐演变发展。通过持续改进和优化,Monorepo 显著提升了大型项目的协作效率,减少了管理成本,并可以作为大规模开发环境下的有效解决方案。