Skip to content

Commit

Permalink
Add docs for catalogs (#553)
Browse files Browse the repository at this point in the history
  • Loading branch information
gluxon authored Jul 7, 2024
1 parent 9510338 commit e5cfef3
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 0 deletions.
147 changes: 147 additions & 0 deletions docs/catalogs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
---
id: catalogs
title: Catalogs
---

Added in: v9.5.0

"_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.

## The Catalog Protocol (`catalog:`)

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

```yaml title="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.

```json title="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.

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

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.

Depending on the scenario, the `catalog:` protocol offers a few [advantages](#advantages) compared to writing version ranges directly that are detailed next.

## 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 to maintain. Duplicated dependencies can conflict at runtime and cause bugs. Duplicates also increase size when using a bundler.
- **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

Catalogs are defined in 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`.

```yaml title="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 that expands to `catalog:default`.

### Named Catalogs

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

```yaml title="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 migrating to a newer version of a dependency piecemeal.

```yaml title="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](./workspaces.md#workspace-protocol-workspace), which is [also replaced on publish](./workspaces.md#publishing-workspace-packages).

For example,

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

Will become the following on publish.

```json title="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 by other workspaces or package managers.

## Caveats

The `pnpm update` command does not yet support catalogs.

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.
18 changes: 18 additions & 0 deletions docs/pnpm-workspace_yaml.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,22 @@ packages:
The root package is always included, even when custom location wildcards are
used.
Catalogs are also defined in the `pnpm-workspace.yaml` file. See [_Catalogs_](./catalogs.md) for details.

```yaml title="pnpm-workspace.yaml"
packages:
- 'packages/*'
catalog:
chalk: ^4.1.2
catalogs:
react16:
react: ^16.7.0
react-dom: ^16.7.0
react17:
react: ^17.10.0
react-dom: ^17.10.0
```

[workspace]: workspaces.md
1 change: 1 addition & 0 deletions sidebars.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
],
"Features": [
"workspaces",
"catalogs",
"aliases",
"completion",
"git_branch_lockfiles"
Expand Down

0 comments on commit e5cfef3

Please sign in to comment.