🧐 什么是 Monorepo?
Monorepo (Monolithic Repository),中文常称为**“单体仓库”**。
用最通俗的话说:把所有的鸡蛋(项目)都放在同一个篮子(Git 仓库)里管理。
- 以前 (Polyrepo / Multi-repo):
- 你有一个后台项目
admin-repo。 - 你有一个用户端项目
h5-repo。 - 你有一个组件库项目
ui-lib-repo。 - 现状:这里有 3 个独立的 Git 仓库。
- 你有一个后台项目
- 现在 (Monorepo):
- 你有一个大仓库
my-company-repo。 - 文件夹
apps/admin是后台。 - 文件夹
apps/h5是用户端。 - 文件夹
packages/ui-lib是组件库。 - 现状:所有代码都在这 1 个 Git 仓库里。
- 你有一个大仓库
💡 为什么要用 Monorepo?解决了什么痛点?
想象一下,你现在的公司有 3 个前端项目,它们都用了同一个 Button 组件。
❌ 传统模式 (Polyrepo) 的噩梦:
- 你发现
Button组件有个 Bug。 - 你去
ui-lib仓库修好它,发布版本v1.0.1到 npm。 - 你去
admin仓库,运行npm update,测试,提交代码。 - 你去
h5仓库,运行npm update,测试,提交代码。 - 痛点:流程繁琐,版本不同步(有的项目忘了升),本地调试困难(你需要
npm link,这玩意儿经常出问题)。
✅ Monorepo 模式的爽点:
- 你在
packages/ui-lib里修好Button。 - 因为所有项目都在一起,
apps/admin和apps/h5瞬间就感知到了变化(直接引用本地文件路径,甚至不需要发 npm 包)。 - 你运行一次测试命令,确保所有受影响的项目都通过。
- 一个 Commit 提交所有更改。
- 优势:代码共享极致简单,版本管理统一,原子化提交。
🏗️ 标准的 Monorepo 目录结构
一个现代前端 Monorepo 通常长这样:
Plaintext
my-monorepo/
├── package.json # 根配置
├── pnpm-workspace.yaml # pnpm 的工作区配置(告诉它哪些是子项目)
├── turbo.json # Turborepo 构建缓存配置
│
├── apps/ # 🚀 应用程序目录 (业务代码)
│ ├── web/ # Next.js 官网
│ ├── admin/ # React + Vite 后台管理
│ └── docs/ # 文档站点
│
└── packages/ # 📦 共享库目录 (基建代码)
├── ui/ # 共享 UI 组件库 (Button, Input)
├── utils/ # 共享工具函数 (formatDate, currency)
├── tsconfig/ # 共享 TS 配置 (所有项目统一标准)
└── eslint-config/ # 共享 Lint 配置🛠️ 怎么实现?(工具链选择)
Monorepo 不是靠手动复制粘贴实现的,它需要工具支持。目前业界最主流的方案是:
pnpm + Turborepo
- pnpm (包管理):
- 它是 Monorepo 的基石。它的 Workspaces (工作区) 功能,允许你在根目录下
npm install一次,它就会帮你在所有子项目里把依赖装好,并把packages/ui自动软链接(Symlink)到apps/web里。
- 它是 Monorepo 的基石。它的 Workspaces (工作区) 功能,允许你在根目录下
- Turborepo (构建工具):
- 由 Vercel 开发。它的核心作用是**“快”**。
- 缓存机制:如果你在
apps/web里改了一行代码,Turborepo 知道apps/admin没变,构建时会直接复用缓存,跳过admin的构建。 - 并行执行:它可以同时跑所有项目的 Lint、Test 和 Build。
⚠️ 架构师的“避坑”指南
Monorepo 虽然好,但也不是没有代价的:
- 仓库体积大: 随着时间推移,
.git会变得巨大。- 解法:使用 Git LFS 管理大文件,或者只 clone 最近的 commit (shallow clone)。
- 权限控制难: 以前不同团队只能看自己的仓库,现在大家都在一个仓库里,对于极其注重保密的公司可能是问题。
- 解法:通常通过 Code Owner 机制来控制谁能合并哪个文件夹的代码。
- CI/CD 变慢: 既然代码都在一起,难道改一行代码就要把所有项目重新部署一遍吗?
- 解法:必须配合 Turborepo 或 Nx 这样的工具,实现“按需构建”(Affected Build)。只构建和部署受影响的应用。