Catalogs

“Catalogs” 是一个 工作空间功能,可将依赖项版本定义为可复用常量。目录中定义的常量稍后可以在 package.json 文件中引用。

The catalog protocol (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 或多包 repo)中,许多包使用相同的依赖项是很常见的。在编写 package.json 文件时,目录可以减少重复,并在此过程中提供一些好处:

  • Maintain unique versions: It's usually desirable to have only one version of a dependency in a workspace. Catalog 让工作区内共同依赖项的版本更容易维护。重复的依赖关系可能会在运行时冲突并导致错误。当使用打包器时,不同版本的重复依赖项也会增大项目体积。
  • Easier upgrades: When upgrading a dependency, only the catalog entry in pnpm-workspace.yaml needs to be edited rather than all package.json files using that dependency. This saves time. Only one line needs to be changed instead of many.
  • Fewer merge conflicts: Since package.json files do not need to be edited when upgrading a dependency, git merge conflicts no longer happen in these files.

Defining catalogs#

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

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

提示

如果你有一个现有的工作区并想使用目录进行迁移,则可以使用以下 codemod:

pnpx codemod pnpm/catalog

Default catalog#

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

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

这些版本范围可以通过 catalog:default 引用。仅有默认目录时,也可以使用特殊的 catalog: 简写。将 catalog: 视为可扩展为 catalog:default 的简写。

Named catalogs#

可以在 catalogs 键下配置具有名称任意选择的多个catalog。

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

Workspace dependencies in a catalog#

Added in: v11.26.0

A catalog entry may hold a workspace: range, so the version a workspace dependency is linked by is written once too:

pnpm-workspace.yaml
catalog:
  '@example/utils': workspace:^
packages/example-app/package.json
{
  "name": "@example/app",
  "dependencies": {
    "@example/utils": "catalog:"
  }
}

pnpm expands the catalog: reference to workspace:^ and then links the workspace project, exactly as if the package.json had declared workspace:^ itself. On publish both protocols are replaced, so the example above ships as "^1.4.0" when @example/utils is at 1.4.0.

发布#

运行 pnpm publish 或者 pnpm 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 包。

设置#

catalogMode#

添加于:v10.12.1

  • 默认值: manual
  • 类型:manual、strict、prefer

控制运行 pnpm add 时是否以及如何将依赖项添加到默认目录中。有三种模式:

  • strict - 仅允许来自目录的依赖版本。在目录版本范围之外添加依赖关系会导致错误。
  • prefer - 优先使用目录版本,但如果未找到兼容版本,则会退回到直接依赖项。
  • manual(默认)——不会自动将依赖项添加到目录中。

Since v11.26.0, a specifier that names a location rather than a version is never moved into a catalog: local paths, local tarballs, tarball URLs, and workspace:<path> ranges stay in the package.json that declares them. Such a specifier is resolved relative to its own project, so one catalog entry could not mean the same directory for every project that references it.

catalogPrune#

添加于:v11.22.0(自 v10.15.0 起为 cleanupUnusedCatalogs)

  • 默认值: false
  • 类型:Boolean

当设置为 true 时,pnpm 将在安装期间删除未使用的目录条目。

cleanupUnusedCatalogs 是该设置已弃用的名称,但仍可继续使用;若两者同时设置,则以 catalogPrune 为准。