2025.09.01
理解 Monorepo:多包管理的概念
🚀 什么是 Monorepo
- 简洁定义:将多个相互关联的项目或库集中在一个 Git 仓库中进行统一管理、开发和发布。
- 形象类比:它就像一个**“超级工厂”**,里面有多个独立运行的生产线(子项目),但所有生产线都共享一套标准化的工具、基础设施和中央管理系统。
✨ 为什么选择 Monorepo
| 优势 | 解决的问题 | Alien v |
|---|---|---|
| 省心 🧹 (统一配置) | 每个项目都需要重复配置 ESLint, Prettier, CI 等工具。 | 统一工具链,一处配置,全局生效,消除配置碎片化 |
| 省时 ⏱️ (高效协作) | 跨项目改动需要频繁切换仓库,提交多次 | 原子化提交,一次提交即可覆盖所有相关项目改动,提升协作效率。 |
| 省空间 💾 (依赖优化) | 多仓库重复安装相同的依赖 | 依赖提升 (Hoisting),共享依赖安装在根目录,节省磁盘空间 |
| 省沟通 💬 (集中透明) | 联调、排查问题和版本对齐复杂 | 代码集中可见,加速联调、版本同步和问题定位。 |
🎯最佳使用场景
- 高内聚性:存在大量内部相互依赖的包/模块(如核心库、工具层、业务组件库)。
- 标准统一化:需要强制推行统一的代码标准(tsconfig, eslint, prettier)。
- 联动发布需求:当某个核心包更新时,依赖它的所有包都需要同步发版。
🔍 Monorepo vs. Multi-repo
| 特性 | Monorepo (集中式) | Multi-repo (分散式) |
|---|---|---|
| 仓库数量 | 1 个大仓库 | N 个小仓库 |
| 跨包协作 | 非常流畅,本地即可引用 | 复杂,需要发布到 npm 或使用 Link |
| 管理复杂度 | CI/CD 流程统一 | CI/CD 流程分散,版本对齐困难 |
🗂 典型目录结构
minivue/
packages/
shared/
reactivity/
vue/
pnpm-workspace.yaml
package.json
⚠️ 易踩的坑与规避
- 坑 1:子包缺少 name 或版本 🧱
- 现象:workspace 无法链接,或 filter 无法命中
- 解决:每个子包
package.json必须包含name;版本可简化为0.0.0
- 坑 2:依赖循环 ♻️(A 依赖 B,B 又依赖 A)
- 现象:构建或运行异常、类型推断混乱
- 解决:抽取
shared层打破环,或下沉到更基础的包
- 坑 3:路径引用混乱 🧭
- 现象:TS 能过但运行时找不到,或反之
- 解决:统一使用包名导入(
@vue/shared),尽量避免跨包相对路径
- 坑 4:版本管理失控 📦
- 现象:部分包忘记升级,导致行为不一致
- 解决:使用 changeset/自研脚本,或统一
workspace:*
🧰 workspace 玩转 Monorepo
1) 根目录配置(只做一次)🏗️
pnpm-workspace.yaml
packages:
- packages/*
- 根
package.json常见配置:
{
"private": true,
"packageManager": "pnpm@X.Y.Z",
"scripts": {
"build": "pnpm -r --filter ./packages... run build",
"dev": "pnpm -r --parallel --filter ./packages/reactivity run dev"
}
}
2) 子包如何相互引用 🔗
- 在子包
package.json里:
{
"dependencies": {
"@vue/shared": "workspace:*"
}
}
- 含义 📝:优先链接本地 workspace 的
@vue/shared,不从 npm 下载。
3) 常用命令 🛠️
- 安装依赖(根目录执行):
pnpm install - 按包执行脚本:
pnpm --filter @scope/pkg run dev - 对全部包执行:
pnpm -r run build - 只对依赖链执行:
pnpm -r --filter @scope/pkg... run build - 装其他包
pnpm install @vue/shared --workspace --filter reactivity