引言
在现代前端和全栈开发中,Monorepo(单体仓库) 已成为管理多项目的流行方案。结合 PNPM 这一高效的包管理工具,可以显著提升依赖管理效率、节省磁盘空间,并优化团队协作。
本文将带你从零搭建一个完整的 Monorepo + PNPM 项目,涵盖:
✅ Monorepo 核心概念
✅ PNPM Workspace 配置
✅ 跨项目依赖管理
✅ 任务执行与优化
✅ 实际应用场景
1. Monorepo 是什么?
1.1 定义
Monorepo(Monolithic Repository) 是一种代码管理策略,将多个相关项目(如前端、后端、共享库)存放在同一个代码仓库中,而非拆分成多个独立仓库(Polyrepo)。
1.2 优势
场景 | Monorepo 优势 | Polyrepo 劣势 |
---|---|---|
多包依赖 | 直接本地引用,无需发布到 npm | 需手动 npm link 或频繁发布测试版 |
统一版本 | 所有项目共享依赖版本,避免冲突 | 各项目依赖版本可能不一致 |
代码复用 | 共享工具库、配置、脚本 | 需复制代码或维护私有 npm 包 |
跨项目修改 | 一次提交即可更新多个项目 | 需跨仓库提交,协调复杂 |
CI/CD | 统一构建、测试和部署流程 | 每个仓库需单独配置 |
1.3 适用场景
- 全栈项目(前端 + 后端 + 共享类型)
- 组件库/工具链(多个相互依赖的 npm 包)
- 微前端/微服务架构
- 企业级大型项目(如 Google、Meta 等公司广泛使用)
2. PNPM 为什么适合 Monorepo?
PNPM 凭借以下特性成为 Monorepo 的理想选择:
- 硬链接 + 符号链接:相同依赖只存储一份,节省磁盘空间。
- 严格依赖结构:避免幽灵依赖(phantom dependencies)。
- 内置 Workspace:原生支持 Monorepo 多包管理。
- 高效安装:比 npm/yarn 更快的依赖安装速度。
3. 实战:搭建 Monorepo + PNPM 项目
3.1 初始化项目
# 创建项目目录
mkdir monorepo-demo && cd monorepo-demo
# 初始化 PNPM(未安装则先运行:npm install -g pnpm)
pnpm init
# 创建 Monorepo 基础结构
mkdir packages
3.2 配置 PNPM Workspace
在根目录创建 pnpm-workspace.yaml
:
packages:
- 'packages/*' # 匹配 packages 下的所有子目录
3.3 创建子项目
(1) 共享工具库(utils)
mkdir -p packages/utils/src
cd packages/utils && pnpm init
编辑 packages/utils/package.json
:
{
"name": "utils",
"version": "1.0.0",
"main": "src/index.js",
"scripts": {
"test": "echo \"Testing utils...\""
}
}
创建工具函数 packages/utils/src/index.js
:
export const add = (a, b) => a + b;
(2) 前端应用(web-app)
mkdir -p packages/web-app/src
cd packages/web-app && pnpm init
编辑 packages/web-app/package.json
,引用本地 utils
:
{
"name": "web-app",
"version": "1.0.0",
"scripts": {
"dev": "echo \"Running web-app...\"",
"test": "echo \"Testing web-app...\""
},
"dependencies": {
"utils": "workspace:*" # 关键!通过 workspace 引用本地包
}
}
(3) 后端服务(api-server)
mkdir -p packages/api-server/src
cd packages/api-server && pnpm init
编辑 packages/api-server/package.json
:
{
"name": "api-server",
"version": "1.0.0",
"scripts": {
"start": "echo \"Starting API server...\"",
"test": "echo \"Testing api-server...\""
},
"dependencies": {
"utils": "workspace:*"
}
}
3.4 安装依赖
# 安装所有子包的依赖(自动处理 workspace 引用)
pnpm install
# 验证依赖树
pnpm why utils
输出示例:
web-app
└── utils workspace:*
api-server
└── utils workspace:*
4. 核心操作
4.1 运行任务
# 启动前端
pnpm --filter web-app run dev
# 测试所有包
pnpm -r run test
4.2 跨包代码引用
在 web-app
中直接使用 utils
:
// packages/web-app/src/index.js
import { add } from 'utils';
console.log(add(1, 2)); // 输出 3
4.3 批量操作
# 给所有包添加 ESLint
pnpm -r add eslint -D
# 仅更新 web-app 的依赖
pnpm --filter web-app update lodash
5. 高级优化
5.1 集成 Turborepo
加速任务执行(如并行构建):
pnpm add turbo -Dw
创建 turbo.json
:
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
}
}
}
5.2 版本管理与发布
使用 changesets
管理版本号:
pnpm add @changesets/cli -Dw
npx changeset init
6. 项目结构总览
monorepo-demo/
├── packages/
│ ├── utils/ # 共享工具库
│ ├── web-app/ # 前端
│ └── api-server/ # 后端
├── pnpm-workspace.yaml # Monorepo 配置
├── package.json # 根项目
└── turbo.json # 任务优化(可选)
7. 总结
- Monorepo 优势:代码复用、统一版本、高效协作。
- PNPM 核心能力:硬链接节省空间、Workspace 原生支持。
- 最佳实践:
- 使用
workspace:*
引用本地包。 - 通过
--filter
精准控制操作范围。 - 结合
Turborepo
或Nx
优化任务执行。
- 使用
希望这篇指南能帮助你高效管理多项目!如果有问题,欢迎留言讨论 🚀