|
| 1 | +--- |
| 2 | +id: catalogs |
| 3 | +title: Catalogs |
| 4 | +--- |
| 5 | + |
| 6 | +Added in: v9.5.0 |
| 7 | + |
| 8 | +"_Catalogs_" are a [workspace feature](./workspaces.md) for defining dependency version ranges as reusable constants. Constants defined in catalogs can later be referenced in `package.json` files. |
| 9 | + |
| 10 | +## The Catalog Protocol (`catalog:`) |
| 11 | + |
| 12 | +Once a catalog is defined in `pnpm-workspace.yaml`, |
| 13 | + |
| 14 | +```yaml title="pnpm-workspace.yaml" |
| 15 | +packages: |
| 16 | + - packages/* |
| 17 | + |
| 18 | +# Define a catalog of version ranges. |
| 19 | +catalog: |
| 20 | + react: ^18.3.1 |
| 21 | + redux: ^5.0.1 |
| 22 | +``` |
| 23 | +
|
| 24 | +The `catalog:` protocol can be used instead of the version range itself. |
| 25 | + |
| 26 | +```json title="packages/example-app/package.json" |
| 27 | +{ |
| 28 | + "name": "@example/app", |
| 29 | + "dependencies": { |
| 30 | + "react": "catalog:", |
| 31 | + "redux": "catalog:" |
| 32 | + } |
| 33 | +} |
| 34 | +``` |
| 35 | + |
| 36 | +This is equivalent to writing a version range (e.g. `^18.3.1`) directly. |
| 37 | + |
| 38 | +```json title="packages/example-app/package.json" |
| 39 | +{ |
| 40 | + "name": "@example/app", |
| 41 | + "dependencies": { |
| 42 | + "react": "^18.3.1", |
| 43 | + "redux": "^5.0.1" |
| 44 | + } |
| 45 | +} |
| 46 | +``` |
| 47 | + |
| 48 | +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. |
| 49 | + |
| 50 | +Depending on the scenario, the `catalog:` protocol offers a few [advantages](#advantages) compared to writing version ranges directly that are detailed next. |
| 51 | + |
| 52 | +## Advantages |
| 53 | + |
| 54 | +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: |
| 55 | + |
| 56 | +- **Maintain unique versions** — It's usually desirable to have only one version of a dependency in a workspace. Catalogs make this easier to maintain. Duplicated dependencies can conflict at runtime and cause bugs. Duplicates also increase size when using a bundler. |
| 57 | +- **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. |
| 58 | +- **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. |
| 59 | + |
| 60 | +## Defining Catalogs |
| 61 | + |
| 62 | +Catalogs are defined in the `pnpm-workspace.yaml` file. There are two ways to define catalogs. |
| 63 | + |
| 64 | +1. Using the (singular) `catalog` field to create a catalog named `default`. |
| 65 | +2. Using the (plural) `catalogs` field to create arbitrarily named catalogs. |
| 66 | + |
| 67 | +### Default Catalog |
| 68 | + |
| 69 | +The top-level `catalog` field allows users to define a catalog named `default`. |
| 70 | + |
| 71 | +```yaml title="pnpm-workspace.yaml" |
| 72 | +catalog: |
| 73 | + react: ^18.2.0 |
| 74 | + react-dom: ^18.2.0 |
| 75 | +``` |
| 76 | + |
| 77 | +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 that expands to `catalog:default`. |
| 78 | + |
| 79 | +### Named Catalogs |
| 80 | + |
| 81 | +Multiple catalogs with arbitrarily chosen names can be configured under the `catalogs` key. |
| 82 | + |
| 83 | +```yaml title="pnpm-workspace.yaml" |
| 84 | +catalogs: |
| 85 | + # Can be referenced through "catalog:react17" |
| 86 | + react17: |
| 87 | + react: ^17.0.2 |
| 88 | + react-dom: ^17.0.2 |
| 89 | +
|
| 90 | + # Can be referenced through "catalog:react18" |
| 91 | + react18: |
| 92 | + react: ^18.2.0 |
| 93 | + react-dom: ^18.2.0 |
| 94 | +``` |
| 95 | + |
| 96 | +A default catalog can be defined alongside multiple named catalogs. This might be useful in a large multi-package repo that's migrating to a newer version of a dependency piecemeal. |
| 97 | + |
| 98 | +```yaml title="pnpm-workspace.yaml" |
| 99 | +catalog: |
| 100 | + react: ^16.14.0 |
| 101 | + react-dom: ^16.14.0 |
| 102 | +
|
| 103 | +catalogs: |
| 104 | + # Can be referenced through "catalog:react17" |
| 105 | + react17: |
| 106 | + react: ^17.0.2 |
| 107 | + react-dom: ^17.0.2 |
| 108 | +
|
| 109 | + # Can be referenced through "catalog:react18" |
| 110 | + react18: |
| 111 | + react: ^18.2.0 |
| 112 | + react-dom: ^18.2.0 |
| 113 | +``` |
| 114 | + |
| 115 | +## Publishing |
| 116 | + |
| 117 | +The `catalog:` protocol is removed when running `pnpm publish`. This is similar to the [`workspace:` protocol](./workspaces.md#workspace-protocol-workspace), which is [also replaced on publish](./workspaces.md#publishing-workspace-packages). |
| 118 | + |
| 119 | +For example, |
| 120 | + |
| 121 | +```json title="packages/example-components/package.json" |
| 122 | +{ |
| 123 | + "name": "@example/components", |
| 124 | + "dependencies": { |
| 125 | + "react": "catalog:react18", |
| 126 | + } |
| 127 | +} |
| 128 | +``` |
| 129 | + |
| 130 | +Will become the following on publish. |
| 131 | + |
| 132 | +```json title="packages/example-components/package.json" |
| 133 | +{ |
| 134 | + "name": "@example/components", |
| 135 | + "dependencies": { |
| 136 | + "react": "^18.3.1", |
| 137 | + } |
| 138 | +} |
| 139 | +``` |
| 140 | + |
| 141 | +The `catalog:` protocol replacement process allows the `@example/components` package to be used by other workspaces or package managers. |
| 142 | + |
| 143 | +## Caveats |
| 144 | + |
| 145 | +The `pnpm update` command does not yet support catalogs. |
| 146 | + |
| 147 | +To update dependencies defined in `pnpm-workspace.yaml`, newer version ranges will need to be chosen manually until a future version of pnpm handles this. |
0 commit comments