307 lines
7.7 KiB
Plaintext
307 lines
7.7 KiB
Plaintext
---
|
|
title: "Catalogs"
|
|
description: "Share common dependency versions across multiple packages in a monorepo"
|
|
---
|
|
|
|
**Catalogs** share dependency versions across the packages in a monorepo. Rather than repeating the same versions in each workspace package, you define them once in the root `package.json` and reference them throughout your project.
|
|
|
|
## Overview
|
|
|
|
Instead of each workspace package specifying its own versions, you:
|
|
|
|
1. Define version catalogs in the root `package.json`
|
|
2. Reference those versions with the `catalog:` protocol
|
|
3. Update every package at once by changing the version in one place
|
|
|
|
Catalogs matter most in large monorepos where dozens of packages depend on the same versions of key dependencies.
|
|
|
|
## How to Use Catalogs
|
|
|
|
### Directory Structure Example
|
|
|
|
Consider a monorepo with the following structure:
|
|
|
|
```
|
|
my-monorepo/
|
|
├── package.json
|
|
├── bun.lock
|
|
└── packages/
|
|
├── app/
|
|
│ └── package.json
|
|
├── ui/
|
|
│ └── package.json
|
|
└── utils/
|
|
└── package.json
|
|
```
|
|
|
|
### 1. Define Catalogs in Root package.json
|
|
|
|
In your root-level `package.json`, add a `catalog` or `catalogs` field within the `workspaces` object:
|
|
|
|
```json package.json icon="file-json"
|
|
{
|
|
"name": "my-monorepo",
|
|
"workspaces": {
|
|
"packages": ["packages/*"],
|
|
"catalog": {
|
|
"react": "^19.0.0",
|
|
"react-dom": "^19.0.0"
|
|
},
|
|
"catalogs": {
|
|
"testing": {
|
|
"jest": "30.0.0",
|
|
"testing-library": "14.0.0"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
`catalog` and `catalogs` also work at the top level of `package.json`.
|
|
|
|
### 2. Reference Catalog Versions in Workspace Packages
|
|
|
|
In your workspace packages, use the `catalog:` protocol to reference versions:
|
|
|
|
```json packages/app/package.json icon="file-json"
|
|
{
|
|
"name": "app",
|
|
"dependencies": {
|
|
"react": "catalog:",
|
|
"react-dom": "catalog:",
|
|
"jest": "catalog:testing"
|
|
}
|
|
}
|
|
```
|
|
|
|
```json packages/ui/package.json icon="file-json"
|
|
{
|
|
"name": "ui",
|
|
"dependencies": {
|
|
"react": "catalog:",
|
|
"react-dom": "catalog:"
|
|
},
|
|
"devDependencies": {
|
|
"jest": "catalog:testing",
|
|
"testing-library": "catalog:testing"
|
|
},
|
|
"peerDependencies": {
|
|
"react": "catalog:"
|
|
}
|
|
}
|
|
```
|
|
|
|
`catalog:` references work in `dependencies`, `devDependencies`, `optionalDependencies`, `peerDependencies`, and as the value of a root [`overrides`](/pm/overrides) rule. A catalog reference behaves exactly as if the catalog's range were written inline.
|
|
|
|
### 3. Run Bun Install
|
|
|
|
Run `bun install` to install all dependencies according to the catalog versions.
|
|
|
|
## Catalog vs Catalogs
|
|
|
|
Bun supports two ways to define catalogs:
|
|
|
|
1. **`catalog`** (singular): A single default catalog for commonly used dependencies
|
|
|
|
```json package.json icon="file-json"
|
|
"catalog": {
|
|
"react": "^19.0.0",
|
|
"react-dom": "^19.0.0"
|
|
}
|
|
```
|
|
|
|
Reference with `catalog:`:
|
|
|
|
```json packages/app/package.json icon="file-json"
|
|
"dependencies": {
|
|
"react": "catalog:"
|
|
}
|
|
```
|
|
|
|
2. **`catalogs`** (plural): Multiple named catalogs for grouping dependencies
|
|
|
|
```json package.json icon="file-json"
|
|
"catalogs": {
|
|
"testing": {
|
|
"jest": "30.0.0"
|
|
},
|
|
"ui": {
|
|
"tailwind": "4.0.0"
|
|
}
|
|
}
|
|
```
|
|
|
|
Reference with `catalog:<name>`:
|
|
|
|
```json packages/app/package.json icon="file-json"
|
|
"dependencies": {
|
|
"jest": "catalog:testing",
|
|
"tailwind": "catalog:ui"
|
|
}
|
|
```
|
|
|
|
## Benefits of Using Catalogs
|
|
|
|
- **Consistency**: All packages use the same version of critical dependencies
|
|
- **Maintenance**: Update a dependency version in one place instead of across multiple `package.json` files
|
|
- **Clarity**: Makes it obvious which dependencies are standardized across your monorepo
|
|
- **Simplicity**: No extra version resolution strategies or external tools
|
|
|
|
## Real-World Example
|
|
|
|
A larger example, for a React application:
|
|
|
|
**Root package.json**
|
|
|
|
```json package.json icon="file-json"
|
|
{
|
|
"name": "react-monorepo",
|
|
"workspaces": {
|
|
"packages": ["packages/*"],
|
|
"catalog": {
|
|
"react": "^19.0.0",
|
|
"react-dom": "^19.0.0",
|
|
"react-router-dom": "^6.15.0"
|
|
},
|
|
"catalogs": {
|
|
"build": {
|
|
"webpack": "5.88.2",
|
|
"babel": "7.22.10"
|
|
},
|
|
"testing": {
|
|
"jest": "29.6.2",
|
|
"react-testing-library": "14.0.0"
|
|
}
|
|
}
|
|
},
|
|
"devDependencies": {
|
|
"typescript": "5.1.6"
|
|
}
|
|
}
|
|
```
|
|
|
|
```json packages/app/package.json icon="file-json"
|
|
{
|
|
"name": "app",
|
|
"dependencies": {
|
|
"react": "catalog:",
|
|
"react-dom": "catalog:",
|
|
"react-router-dom": "catalog:",
|
|
"@monorepo/ui": "workspace:*",
|
|
"@monorepo/utils": "workspace:*"
|
|
},
|
|
"devDependencies": {
|
|
"webpack": "catalog:build",
|
|
"babel": "catalog:build",
|
|
"jest": "catalog:testing",
|
|
"react-testing-library": "catalog:testing"
|
|
}
|
|
}
|
|
```
|
|
|
|
```json packages/ui/package.json icon="file-json"
|
|
{
|
|
"name": "@monorepo/ui",
|
|
"dependencies": {
|
|
"react": "catalog:",
|
|
"react-dom": "catalog:"
|
|
},
|
|
"devDependencies": {
|
|
"jest": "catalog:testing",
|
|
"react-testing-library": "catalog:testing"
|
|
}
|
|
}
|
|
```
|
|
|
|
```json packages/utils/package.json icon="file-json"
|
|
{
|
|
"name": "@monorepo/utils",
|
|
"dependencies": {
|
|
"react": "catalog:"
|
|
},
|
|
"devDependencies": {
|
|
"jest": "catalog:testing"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Updating Versions
|
|
|
|
To update versions across all packages, change the version in the root package.json:
|
|
|
|
```json package.json icon="file-json"
|
|
"catalog": {
|
|
"react": "^19.1.0", // Updated from ^19.0.0
|
|
"react-dom": "^19.1.0" // Updated from ^19.0.0
|
|
}
|
|
```
|
|
|
|
Then run `bun install` to update all packages.
|
|
|
|
## Adding to the catalog with `bun add`
|
|
|
|
`bun add --catalog` adds the entry to the root catalog and writes `"catalog:"` to the current package; `--catalog=<name>` adds it to `catalogs.<name>` and writes `"catalog:<name>"`. Bun reuses an existing catalog entry unless you pass an explicit version. See [`bun add --catalog`](/pm/cli/add#--catalog).
|
|
|
|
```bash terminal icon="terminal"
|
|
bun add react --catalog
|
|
```
|
|
|
|
Even without the flag, `bun add react` (no version) writes `"catalog:"` when the default catalog already lists `react`. Pass a version to write a concrete range instead.
|
|
|
|
## Lockfile Integration
|
|
|
|
Bun's lockfile tracks catalog versions, so installs are consistent across environments. The lockfile includes:
|
|
|
|
- The catalog definitions from your package.json
|
|
- The resolution of each cataloged dependency
|
|
|
|
```json bun.lock(excerpt) icon="file-json"
|
|
{
|
|
"lockfileVersion": 2,
|
|
"workspaces": {
|
|
"": {
|
|
"name": "react-monorepo",
|
|
},
|
|
"packages/app": {
|
|
"name": "app",
|
|
"dependencies": {
|
|
"react": "catalog:",
|
|
"react-dom": "catalog:",
|
|
...
|
|
},
|
|
},
|
|
...
|
|
},
|
|
"catalog": {
|
|
"react": "^19.0.0",
|
|
"react-dom": "^19.0.0",
|
|
...
|
|
},
|
|
"catalogs": {
|
|
"build": {
|
|
"webpack": "5.88.2",
|
|
...
|
|
},
|
|
...
|
|
},
|
|
"packages": {
|
|
...
|
|
}
|
|
}
|
|
```
|
|
|
|
## Limitations and Edge Cases
|
|
|
|
- Catalog references must match a dependency defined in either `catalog` or one of the named `catalogs`
|
|
- Bun ignores empty strings and whitespace in catalog names and treats them as the default catalog
|
|
- `catalog:default` is the same as `catalog:`. You can define the default catalog as either `catalog` or `catalogs.default`, but a package listed in both is an error
|
|
- Invalid dependency versions in catalogs fail to resolve during `bun install`
|
|
- `catalog:` only works in the root and workspace `package.json` files. Inside a published package it fails to resolve. Publish with `bun publish` or `bun pm pack`, which replace it with the real range (see [Publishing](#publishing))
|
|
|
|
## Publishing
|
|
|
|
When you run `bun publish` or `bun pm pack`, Bun replaces `catalog:` references
|
|
in your `package.json` with the resolved version numbers. The published package
|
|
includes regular semver strings and no longer depends on your catalog
|
|
definitions.
|