Langsung ke konten utama
Versi: 9.x

Catalogs

Added in: v9.5.0

"Catalogs" are a workspace feature for defining dependency version ranges as reusable constants. Constants defined in catalogs can later be referenced in package.json files.

The Catalog Protocol (catalog:)

Once a catalog is defined in pnpm-workspace.yaml,

pnpm-workspace.yaml
packages:
- packages/*

# Define a catalog of version ranges.
catalog:
react: ^18.3.1
redux: ^5.0.1

The catalog: protocol can be used instead of the version range itself.

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

This is equivalent to writing a version range (e.g. ^18.3.1) directly.

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

Depending on the scenario, the catalog: protocol offers a few advantages compared to writing version ranges directly that are detailed next.

The catalog: protocol allows an optional name after the colon (ex: catalog:name) to specify which catalog should be used. When a name is omitted, the default catalog is used.

Advantages

In a workspace (i.e. monorepo or multi-package repo) it's common for the same dependency to be used by many packages. Catalogs reduce duplication when authoring package.json files and provide a few benefits in doing so:

  • Maintain unique versions — It's usually desirable to have only one version of a dependency in a workspace. Catalogs make this easier maintain. Duplicated dependencies can conflict at runtime causing bugs. Duplicates also increase size when bundling.
  • Easier upgrades — When upgrading a dependency, only the catalog in pnpm-workspace.yaml needs to be edited rather than all package.json files using that dependency. This saves time when editing lots of files.
  • 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

Catalogs are defined the pnpm-workspace.yaml file. There are two ways to define catalogs.

  1. Using the (singular) catalog field to create a catalog named default.
  2. Using the (plural) catalogs field to create arbitrarily named catalogs.

Default Catalog

The top-level catalog field allows users to define a catalog named default.

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

These version ranges can be referenced through catalog:default. For the default catalog only, a special catalog: shorthand can also be used. Think of catalog: as a shorthand expanding to catalog:default.

Named Catalogs

Multiple catalogs with arbitrarily chosen names can be configured under the catalogs key.

pnpm-workspace.yaml
catalogs:
# Can be referenced through "catalog:react17"
react17:
react: ^17.0.2
react-dom: ^17.0.2

# Can be referenced through "catalog:react18"
react18:
react: ^18.2.0
react-dom: ^18.2.0

A default catalog can be defined alongside multiple named catalogs. This might be useful in a large multi-package repo that's incrementally migrating to a newer version of a dependency piecemeal.

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

catalogs:
# Can be referenced through "catalog:react17"
react17:
react: ^17.0.2
react-dom: ^17.0.2

# Can be referenced through "catalog:react18"
react18:
react: ^18.2.0
react-dom: ^18.2.0

Publishing

The catalog: protocol is removed when running pnpm publish. This is similar to the workspace: protocol, which is also replaced on publish.

Misalnya,

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

Will become the following on publish.

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

The catalog: protocol replacement process allows the @example/components package to be used other workspaces or package managers.

Caveats

The pnpm update command does not yet support catalogs.

Newer versions will need to be edited in pnpm-workspace.yaml manually until a future version of pnpm handles this.