Skip to content

pnpm-workspace.yaml 配置详解

本文档逐项解释 pnpm-workspace.yaml.npmrc 中的每一个配置项——它是什么、为什么这么配、改了会怎样。


pnpm-workspace.yaml

catalogMode: strict

yaml
catalogMode: strict

package.json 中的依赖必须用 "catalog:" 引用,不能直接写版本号。违反则在 pnpm install 时报错。

为什么:阻止 pnpm add 不加 --save-catalog 引入依赖,防止版本漂移。

packages

yaml
packages:
  - 'apps/*'
  - 'packages/*'

声明哪些目录是 pnpm workspace 成员。当前是 apps/(3 个应用)和 packages/(5 个共享包),共 8 个 workspace 包。

hoisting: false

yaml
hoisting: false

禁止 pnpm 默认的依赖提升行为。默认 true 时,所有依赖会被提升到 node_modules/.pnpm/node_modules;设为 false 后,每个包只能访问自己 package.json 中声明的依赖。

为什么:严格的依赖隔离。不会出现"包 A 没声明 lodash 但能 import 到"的幽灵依赖(phantom dependency)问题。

例外:5 个工具链包需要在 .npmrc 中通过 public-hoist-pattern 提升到根 node_modules(见下文)。

overrides

yaml
overrides:
  glob: 11.1.0
  lru-cache: 11.3.6

强制整个依赖树中这两个包统一为指定版本。无论间接依赖声明了 glob@10.x 还是 glob@9.x,pnpm 只用 11.1.0

为什么globlru-cache 是极底层的工具库,被几十个间接依赖引用。不统一版本会装多份,浪费空间 + 可能运行时冲突。

minimumReleaseAgeExclude

yaml
minimumReleaseAgeExclude:
  - '@dotenvx/dotenvx@2.19.0'
  - '@dotenvx/primitives@2.1.1'

pnpm 的安全机制:新发布的包要等一段"冷却期"才能安装(防止供应链攻击——恶意包被发现前有时间窗口)。这两个 @dotenvx 包发布频繁,不加白名单 CI 的 pnpm install 会报错。

为什么只排这两个:它们是项目中唯一频繁发布的包。排除的是精确版本号@2.19.0),不影响其他版本的安全检查。

allowBuilds

pnpm 默认禁止包执行 postinstall 脚本(安全措施)。allowBuilds 白名单允许特定包执行。

yaml
allowBuilds:
  '@alicloud/openapi-core': true  # 阿里云 SDK,需要 postinstall
  '@compodoc/compodoc': true      # NestJS 文档生成器
  '@nestjs/core': true            # NestJS 核心,需要编译原生扩展
  '@parcel/watcher': true         # 文件监听原生模块
  '@scarf/scarf': true            # 匿名使用统计(可选)
  '@sentry/cli': true             # Sentry 错误追踪 CLI
  '@swc/core': true               # SWC 编译器,Rust 原生模块
  core-js: true                   # Polyfill 库
  esbuild: true                   # Go 原生模块(Vite/Vitest 编译引擎)
  json-editor-vue: true           # JSON 编辑器组件
  msgpackr-extract: true          # 序列化库原生模块
  rs-module-lexer: true           # Rust 模块解析器
  sharp: true                     # 图片处理(libvips 原生模块)
  simple-git-hooks: true          # Git hooks 管理器
  unrs-resolver: true             # Rust 路径解析器
  vue-demi: true                  # Vue 2/3 兼容层
类别为什么需要
原生编译@swc/core, esbuild, sharp, @parcel/watcherRust/Go/C++ 原生模块,必须编译才能用
框架核心@nestjs/coreNestJS 依赖注入引擎
工具链simple-git-hooks, @compodoc/compodoc, @sentry/cliGit hooks / 文档生成 / 错误上报
云 SDK@alicloud/openapi-core阿里云 API 调用
Polyfillcore-js浏览器兼容性
兼容层vue-demiVue 2/3 双版本兼容
序列化msgpackr-extract, unrs-resolver, rs-module-lexerRust 原生模块,性能优化
组件json-editor-vueJSON 编辑器
统计@scarf/scarf可选匿名使用统计

.npmrc

strict-peer-dependencies=true

peerDependencies 版本不匹配时 pnpm install 直接报错。

engine-strict=true

package.jsonengines.node >= 24.13.0 不满足时拒绝安装。

save-exact=true

pnpm add 默认保存精确版本(不用 ^ 前缀)。配合 catalog 使用。

public-hoist-pattern[]

ini
public-hoist-pattern[]=*turbo*
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*simple-git-hooks*
public-hoist-pattern[]=*@swc*
public-hoist-pattern[]=*esbuild*

将匹配的包从 node_modules/.pnpm/ 提升到根 node_modules/。仅用于必须在根目录运行的 CLI 工具

模式提升的包原因
*turbo*turbo根目录执行 turbo run
*eslint*eslint + 插件统一 ESLint 配置解析
*simple-git-hooks*simple-git-hookspostinstall 注册 hooks
*@swc*@swc/core, @swc/cliServer SWC 编译器
*esbuild*esbuildVite、vitest、tsx 共用

相关文档

基于 MIT 许可发布