pnpm Workspace 概述
pnpm workspaces 通过 pnpm-workspace.yaml、用于本地包链接的 workspace: 协议以及可跨特定包运行命令的强大过滤功能,提供内置的 monorepo 支持。Catalogs 可在所有工作区包之间强制统一依赖版本。
使用场景:多包仓库、含消费应用的共享库、跨包一致的依赖管理、在一部分包子集上运行命令。
不适用场景:单包项目、已使用 npm/yarn workspaces 的项目(需迁移)、需要各包浮动依赖版本的项目。
快速参考
模式 / API 与配置 / 要点
定义工作区:pnpm-workspace.yaml 配合 packages globs;globs 匹配包含 package.json 的目录。
链接本地包:"dep": "workspace:*";始终解析为本地工作区包。
带版本范围链接:"dep": "workspace:^1.0.0";若本地版本不满足该范围则安装失败。
默认 catalog:pnpm-workspace.yaml 中的 catalog: 键;依赖版本的单一事实来源。
命名 catalog:catalogs: 键配合命名分组;可维护多组版本集(如 react18、react17)。
在包中使用 catalog:"dep": "catalog:" 或 "dep": "catalog:name";在 pnpm publish 时解析为实际版本。
按名称过滤:--filter <name> 或 -F <name>;精确名称或 glob 模式(@scope/*)。
带依赖过滤:--filter "foo...";包及其所有依赖。
带依赖方过滤:--filter "...foo";包以及所有依赖它的包。
按目录过滤:--filter "./packages/app";某目录路径下的所有包。
按 git 变更过滤:--filter "[origin/main]";自某提交或分支以来发生变更的包。
从过滤中排除:--filter "!foo";将匹配的包从选择中移除。
在包中运行脚本:pnpm --filter <pkg> <script>;仅在匹配的包中运行脚本。
递归运行:pnpm -r run <script>;在所有工作区包中运行脚本。
全部安装:pnpm install;整个工作区共用一个锁文件。
发布工作区包:pnpm publish;将 workspace: 和 catalog: 替换为真实版本。
注入工作区依赖:.npmrc 中 inject-workspace-packages=true;以硬链接代替符号链接;deploy 所必需。
脚本安全(v10+):package.json 中的 allowBuilds;生命周期脚本默认被阻止,需按依赖选择加入。
常见错误
错误 / 正确做法
使用 workspace:* 后按原样发布;pnpm 会在发布时自动将 workspace:* 替换为真实版本。
忘记在 packages: 中列出目录;每个包目录都必须匹配 pnpm-workspace.yaml 中的某个 glob。
在工作区包中使用 npm install;始终从工作区根目录使用 pnpm install。
在多个包中硬编码重复版本;使用 catalog: 集中定义版本。
在子包内运行 pnpm install;应从工作区根目录运行,用 --filter 定位包。
期望 --filter 匹配目录名;--filter 匹配 package.json 的 name 字段,而非目录名。
在 zsh 中未转义 ! 以用于排除过滤;使用 ! 或对过滤条件加引号:--filter="!foo"。
对非工作区依赖使用 workspace:;workspace: 协议仅对工作区中定义的包有效。
pnpm 10 升级后生命周期脚本失败;pnpm 10 默认阻止脚本,需在配置的 allowBuilds 中加入依赖。
未启用 inject-workspace-packages 就使用 pnpm deploy;在 .npmrc 中设置 inject-workspace-packages=true(pnpm 10 必需)。
委派
工作区脚手架:使用 Explore agent 发现现有包结构。
依赖审计:使用 Task agent 检查各包之间的版本一致性。
如果 turborepo 技能可用,将构建编排、任务缓存和 CI 优化委派给它。如果 changesets 技能可用,将版本管理、变更日志生成和 npm 发布委派给它。
参考资料
工作区搭建、workspace 协议与 catalogs。
为定向命令过滤包。
跨工作区包共享配置。
Monorepo 集成:pnpm + Turborepo + Changesets 流水线。