Monorepo 概念与工具
Monorepo 的定义、优缺点及 Lerna、Pnpm Workspace 的使用
问题
什么是 Monorepo?常用的 Monorepo 工具有哪些?如何配置和使用?
解答
什么是 Monorepo
Monorepo(单一代码仓库)是将多个项目放在同一个 Git 仓库中管理的策略。
# Multirepo(多仓库)
├── repo-app/
├── repo-ui-components/
└── repo-utils/
# Monorepo(单仓库)
└── monorepo/
├── apps/
│ └── web/
└── packages/
├── ui-components/
└── utils/
Monorepo vs Multirepo
| 特性 | Monorepo | Multirepo |
|---|---|---|
| 代码共享 | 简单直接 | 需要发布 npm 包 |
| 依赖管理 | 统一版本 | 各自管理 |
| 原子提交 | 支持 | 不支持 |
| 构建复杂度 | 较高 | 较低 |
| 仓库体积 | 较大 | 较小 |
Pnpm Workspace
Pnpm 内置 workspace 支持,是目前最推荐的方案。
# pnpm-workspace.yaml
packages:
- 'packages/*'
- 'apps/*'
// package.json(根目录)
{
"name": "my-monorepo",
"private": true,
"scripts": {
"dev": "pnpm -r run dev",
"build": "pnpm -r run build",
"test": "pnpm -r run test"
}
}
// packages/utils/package.json
{
"name": "@my/utils",
"version": "1.0.0",
"main": "dist/index.js",
"scripts": {
"build": "tsc",
"dev": "tsc --watch"
}
}
// apps/web/package.json
{
"name": "@my/web",
"version": "1.0.0",
"dependencies": {
// workspace: 协议引用本地包
"@my/utils": "workspace:*"
}
}
常用命令:
# 安装所有依赖
pnpm install
# 给指定包添加依赖
pnpm add lodash --filter @my/web
# 给所有包添加开发依赖
pnpm add typescript -Dw
# 运行指定包的脚本
pnpm --filter @my/web dev
# 运行所有包的脚本
pnpm -r run build
Lerna
Lerna 专注于版本管理和发布流程。
// lerna.json
{
"version": "independent",
"npmClient": "pnpm",
"useWorkspaces": true,
"command": {
"publish": {
"conventionalCommits": true,
"message": "chore(release): publish"
}
}
}
# 初始化
npx lerna init
# 查看变更的包
npx lerna changed
# 版本升级
npx lerna version
# 发布到 npm
npx lerna publish
# 在所有包中执行命令
npx lerna run build
Turborepo
Turborepo 专注于构建优化,提供缓存和并行执行。
// turbo.json
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
// 依赖其他包的 build 先完成
"dependsOn": ["^build"],
// 输出目录,用于缓存
"outputs": ["dist/**"]
},
"dev": {
"cache": false,
"persistent": true
},
"test": {
"dependsOn": ["build"],
"outputs": []
}
}
}
# 构建所有包(自动处理依赖顺序)
npx turbo run build
# 并行开发
npx turbo run dev
# 只构建变更的包
npx turbo run build --filter=...[HEAD^]
完整项目结构示例
my-monorepo/
├── pnpm-workspace.yaml
├── package.json
├── turbo.json
├── apps/
│ ├── web/
│ │ ├── package.json
│ │ └── src/
│ └── admin/
│ ├── package.json
│ └── src/
├── packages/
│ ├── ui/
│ │ ├── package.json
│ │ └── src/
│ ├── utils/
│ │ ├── package.json
│ │ └── src/
│ └── config/
│ ├── eslint/
│ └── tsconfig/
└── .github/
└── workflows/
工具选择建议
┌─────────────────────────────────────────────────┐
│ 需求 推荐工具 │
├─────────────────────────────────────────────────┤
│ 依赖管理 pnpm workspace │
│ 版本发布 lerna / changesets │
│ 构建优化 turborepo / nx │
│ 综合方案 pnpm + turbo │
└─────────────────────────────────────────────────┘
关键点
- Monorepo 将多个项目放在同一仓库,便于代码共享和统一管理
- Pnpm Workspace 通过
workspace:协议实现本地包引用,依赖安装高效 - Lerna 擅长版本管理和 npm 发布,支持 independent 和 dbpnk 两种版本模式
- Turborepo 提供增量构建和远程缓存,大幅提升构建速度
- 推荐组合:Pnpm + Turborepo,兼顾依赖管理和构建性能
目录