monorepo
(单一代码仓库)是一种代码管理策略,指将多个相关项目(或模块)存放在同一个代码仓库中,而不是为每个项目单独创建仓库。它与传统的 polyrepo
(多仓库)形成对比,适用于需要跨项目共享代码、统一维护和协作的场景。
核心概念
-
传统多仓库(Polyrepo) :每个项目独立一个仓库,代码隔离,依赖通过包管理器(如 npm)共享。
text
复制
css├── project-1-repo │ ├── src │ └── package.json ├── project-2-repo │ ├── src │ └── package.json └── shared-library-repo ├── src └── package.json
-
单一仓库(Monorepo) :所有项目集中在一个仓库,代码和工具链统一管理。
text
复制
perlmy-monorepo/ ├── apps/ │ ├── web-app/ # 前端应用 │ │ └── package.json │ └── mobile-app/ # 移动端应用 │ └── package.json ├── packages/ │ ├── shared-ui/ # 共享 UI 组件库 │ │ └── package.json │ └── utils/ # 通用工具库 │ └── package.json ├── package.json # 根目录的公共配置 └── turbo.json # 构建工具配置(如 Turborepo)
核心优势
-
代码共享与复用
- 跨项目直接引用本地模块(如组件、工具函数),无需发布到包管理器。
- 修改共享代码后,所有依赖项目可立即生效,减少版本同步问题。
-
统一工作流
- 集中管理构建、测试、代码规范等工具链配置(如 ESLint、TypeScript)。
- 批量执行命令(如
lint
、test
),提升效率。
-
原子化提交
- 跨项目的代码修改可在一次提交中完成,保证变更的原子性。
- 便于追踪代码变更对多项目的影响。
-
依赖管理优化
- 通过
workspaces
(npm/yarn/pnpm)统一管理依赖版本,避免重复安装。 - 依赖提升(Hoisting)减少磁盘占用。
- 通过
常见工具
工具 | 特点 |
---|---|
Lerna | 早期主流工具,支持包版本管理和发布(需结合 npm/yarn)。 |
Turborepo | 高性能构建工具,利用缓存加速任务执行(由 Vercel 维护)。 |
Nx | 支持多种语言(JS/React、Python等),提供依赖分析和任务编排。 |
Rush | 微软开发,强调大规模仓库的稳定性和性能优化。 |
pnpm Workspaces | 基于 pnpm 的轻量级方案,依赖复用效率高。 |
适用场景
-
多项目共享代码
- 多个前端应用共用组件库、工具函数或配置。
- 微前端架构中的基座与子应用协同开发。
-
全栈项目
- 前后端代码共存(如 Next.js + NestJS),方便接口联调。
-
工具链统一
- 企业内部多个 CLI 工具或 SDK 的统一维护。
-
开源项目
- 如 Babel、React、Vue 等将核心库与周边生态(插件、文档)集中管理。
挑战与缺点
-
仓库体积膨胀
- 项目数量增多后,克隆和构建时间可能变长。
- 优化:使用按需下载(如 Git Sparse Checkout)、增量构建工具(Turborepo)。
-
权限管理复杂
- 所有代码在同一仓库,需精细控制模块访问权限。
- 解决:结合目录级权限工具(如 Git Submodules 或代码托管平台的分支保护)。
-
工具链复杂性
- 需要配置适合 Monorepo 的构建、测试和发布流程。
- 建议:优先选择开箱即用的工具(如 Turborepo、Nx)。
示例:基于 pnpm 的 Monorepo
-
初始化仓库并安装 pnpm:
perlmkdir my-monorepo && cd my-monorepo pnpm init
-
启用 Workspaces(在根目录
package.json
中配置):json{ "name": "my-monorepo", "private": true, "workspaces": ["apps/*", "packages/*"] }
-
创建子项目:
bashmy-monorepo/ ├── apps/ │ └── web-app/package.json # 引用 packages/shared-ui └── packages/ └── shared-ui/package.json
-
安装依赖(自动提升公共依赖到根目录):
pnpm install