跳到主要内容
版本:10.x

目录

"目录" 是一个工作空间特性,用于将依赖项的版本范围定义为可重用的常量。在目录中定义的常量后续可以在 package.json 文件中引用。

目录协议 (catalog:)

当在 pnpm-workspace.yaml 中定义了一个目录后,

pnpm-workspace.yaml
packages:
- packages/*

# 定义一个版本范围的目录
catalog:
react: ^18.3.1
redux: ^5.0.1

可以使用 catalog: 协议来代替版本范围本身。

packages/example-app/package.json
{
"name": "@example/app",
"dependencies": {
"react": "catalog:",
"redux": "catalog:"
}
}

这等同于直接写入版本范围(例如 ^18.3.1)。

packages/example-app/package.json
{
"name": "@example/app",
"dependencies": {
"react": "^18.3.1",
"redux": "^5.0.1"
}
}

你可以在以下字段中使用 catalog: 协议:

  • package.json
    • dependencies
    • devDependencies
    • peerDependencies
    • optionalDependencies
  • pnpm-workspace.yaml
    • overrides

catalog: 协议允许在冒号后面添加可选的名称(例如:catalog:name)来指定应该使用哪个目录。当省略名称时,将使用默认目录。

根据具体场景,与直接编写版本范围相比,catalog: 协议提供了一些优势,下面将详细介绍。

优势

在工作空间(即 monorepo 或多包仓库)中,同一个依赖项经常被多个包使用。目录在编写 package.json 文件时可以减少重复,并提供以下好处:

  • 维护唯一版本 — 在工作空间中通常希望一个依赖项只有一个版本。目录使这更容易维护。重复的依赖项可能在运行时发生冲突并导致 bug。在使用打包工具时,重复也会增加体积。
  • 更容易升级 — 在升级依赖项时,只需要编辑 pnpm-workspace.yaml 中的目录条目,而不是编辑所有使用该依赖项的 package.json 文件。这节省了时间 — 只需要修改一行而不是多行。
  • 更少的合并冲突 — 由于升级依赖项时不需要编辑 package.json 文件,这些文件中不再会出现 git 合并冲突。

定义目录

目录在 pnpm-workspace.yaml 文件中定义。有两种方式定义目录。

  1. 使用(单数)catalog 字段创建一个名为 default 的目录。
  2. 使用(复数)catalogs 字段创建任意命名的目录。
提示

如果你有一个现有的工作空间想要迁移到使用目录,你可以使用以下 codemod

pnpx codemod pnpm/catalog

默认目录

顶层的 catalog 字段允许用户定义一个名为 default 的目录。

pnpm-workspace.yaml
catalog:
react: ^18.2.0
react-dom: ^18.2.0

这些版本范围可以通过 catalog:default 引用。仅对于默认目录,也可以使用特殊的 catalog: 简写方式。可以把 catalog: 看作是 catalog:default 的简写形式。

命名目录

可以在 catalogs 键下配置多个任意命名的目录。

pnpm-workspace.yaml
catalogs:
# 可以通过 "catalog:react17" 引用
react17:
react: ^17.0.2
react-dom: ^17.0.2

# 可以通过 "catalog:react18" 引用
react18:
react: ^18.2.0
react-dom: ^18.2.0

可以在多个命名目录的同时定义一个默认目录。这在大型多包仓库中逐步迁移到依赖项的新版本时可能会很有用。

pnpm-workspace.yaml
catalog:
react: ^16.14.0
react-dom: ^16.14.0

catalogs:
# 可以通过 "catalog:react17" 引用
react17:
react: ^17.0.2
react-dom: ^17.0.2

# 可以通过 "catalog:react18" 引用
react18:
react: ^18.2.0
react-dom: ^18.2.0

发布

在运行 pnpm publishpnpm pack 时,catalog: 协议会被移除。这类似于 workspace: 协议,它在发布时也会被替换

例如,

packages/example-components/package.json
{
"name": "@example/components",
"dependencies": {
"react": "catalog:react18",
}
}

在发布时会变成:

packages/example-components/package.json
{
"name": "@example/components",
"dependencies": {
"react": "^18.3.1",
}
}

catalog: 协议的替换过程使得 @example/components 包可以被其他工作空间或包管理器使用。

注意事项

pnpm update 命令目前还不支持目录。

在 pnpm 的未来版本支持之前,需要手动为 pnpm-workspace.yaml 中定义的依赖项选择更新的版本范围。