Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add docs for catalogs #553

Merged
merged 1 commit into from
Jul 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading