pnpm-workspace.yaml 是 pnpm 管理 Monorepo(单体仓库)的核心配置文件。它定义了哪些目录属于当前工作区,并提供了许多强大的全局依赖管理策略。
以下是一份生产环境级别的详细配置说明及完整模板。
📖 核心配置项详解
1. packages (必选)
定义哪些目录属于 pnpm workspace。支持 glob 模式。
*:匹配当前目录下的一级子目录。**:匹配任意深度的子目录。!:排除特定目录。
2. catalog (pnpm v9+ 强烈推荐)
依赖目录。用于在 Monorepo 中统一管理依赖版本,解决“版本碎片化”问题。
default:默认目录。- 也可以自定义多个目录(如
react18,react19),方便平滑升级。
3. allowBuilds (安全白名单)
当全局设置了 ignore-scripts=true 时,此列表中的包被允许执行 preinstall / postinstall 脚本。
4. ignoredBuiltDependencies (构建黑名单)
无论全局设置如何,强制跳过这些包的安装/构建脚本。常用于那些构建极慢、容易报错,且你确信不需要其构建步骤的包。
5. peerDependencyRules (对等依赖规则)
用于消除烦人的 peer dependency 警告,或强制解决版本冲突。
ignoreMissing:忽略缺失的 peer 依赖警告。allowedVersions:放宽对 peer 依赖的版本要求。
📝 完整配置模板 (可直接复制使用)
# =========================================================
# pnpm-workspace.yaml
# =========================================================
# 1. 定义工作区包含的目录 (必填)
packages:
# 包含 apps 目录下所有一级子目录 (如 apps/web, apps/admin)
- 'apps/*'
# 包含 packages 目录下所有一级子目录 (如 packages/ui, packages/utils)
- 'packages/*'
# 包含 components 目录下的任意深度子目录
- 'components/**'
# 排除特定的测试目录或废弃目录
- '!packages/deprecated-*'
- '!**/test/**'
# 2. 依赖目录 (Catalogs) - pnpm v9+ 特性
catalog:
# 默认目录,子项目可通过 "catalog:" 引用
react: ^18.2.0
react-dom: ^18.2.0
typescript: ^5.3.0
vite: ^5.0.0
# 自定义目录:例如为某个旧项目保留的 react 17 版本
# react17:
# react: ^17.0.2
# react-dom: ^17.0.2
# 3. 构建脚本控制 (安全与性能)
# 允许以下包执行 postinstall 等脚本 (通常是需要下载二进制文件或编译 C++ 的包)
allowBuilds:
- 'esbuild'
- 'esbuild-*'
- '@swc/core'
- 'sharp'
- 'prisma'
- '@prisma/client'
# 强制忽略以下包的构建脚本 (即使它们请求执行)
ignoredBuiltDependencies:
- 'core-js' # 经常弹出赞助提示,可忽略
- 'vue-demi' # 某些情况下不需要其 postinstall
# 4. 依赖解析规则 (解决警告与冲突)
peerDependencyRules:
# 忽略特定包的 peer 依赖缺失警告
ignoreMissing:
- 'react'
- 'react-dom'
- '@babel/core'
# 允许特定包使用更宽泛的 peer 依赖版本 (解决 "wanted x but got y" 警告)
allowedVersions:
# 允许所有包将 react 的 peer 依赖视为满足 ^18.0.0
react: ^18.0.0
# 针对特定包放宽限制
'eslint-plugin-react':
eslint: ^8.0.0
# 5. 全局依赖覆盖 (Overrides)
# 强制整个 workspace 使用特定版本的依赖,常用于修复安全漏洞或统一底层库
overrides:
# 强制所有子项目使用安全的 lodash 版本
lodash: ^4.17.21
# 强制使用特定版本的 node-fetch (修复 CVE)
node-fetch: ^2.6.7
# 覆盖某个包内部的子依赖
'some-package>unsafe-dep': ^1.0.0🔗 如何在 package.json 中使用这些配置?
配置好 pnpm-workspace.yaml 后,子项目中的 package.json 会变得极其简洁:
场景 A:使用 Catalog (pnpm v9+)
{
"name": "@my-org/web-app",
"dependencies": {
"react": "catalog:",
"react-dom": "catalog:",
"typescript": "catalog:"
}
}注:catalog: 告诉 pnpm:“去 pnpm-workspace.yaml 的 catalog 里找这个包的版本”。
场景 B:使用自定义 Catalog
{
"name": "@my-org/legacy-app",
"dependencies": {
"react": "catalog:react17",
"react-dom": "catalog:react17"
}
}场景 C:引用 Workspace 内的本地包
{
"name": "@my-org/web-app",
"dependencies": {
"@my-org/ui": "workspace:*",
"@my-org/utils": "workspace:^1.0.0"
}
}注:workspace:\* 表示始终链接本地最新版本;workspace:^1.0.0 表示链接本地版本,但发布时会转换为正常的 semver 范围。
⚠️ 常见坑点与注意事项
-
pnpm-workspace.yaml必须放在项目根目录:与根目录的package.json同级。 -
与
.npmrc的关系:
pnpm-workspace.yaml专注于 Workspace 结构、Catalog 和 pnpm 专属的高级依赖规则。- 一些通用的 npm 配置(如
registry、shamefully-hoist、全局的ignore-scripts)仍然建议放在根目录的.npmrc文件中。两者互补,不冲突。
-
修改配置后需重新安装:如果你修改了
packages路径或catalog版本,务必删除node_modules和pnpm-lock.yaml,然后重新运行pnpm install,否则可能会出现幽灵依赖或版本未更新的问题。 -
Glob 语法的陷阱:
packages/*只匹配packages下的一级目录。如果你的结构是packages/libs/core,必须写成packages/**或packages/*/*。
通过合理配置这个文件,你可以将 Monorepo 的依赖管理从“混乱的噩梦”变成“高度可控的工程化利器”。
