Skip to main content
Bun 中的目录(Catalogs)提供了一种简单的方式,在 monorepo 中跨多个包共享通用依赖版本。你无需在每个工作区包中反复指定相同版本,而只需在根目录的 package.json 中定义一次,并在整个项目中统一引用。

概述

与传统的依赖管理方式中每个工作区包需要独立指定版本不同,目录让你能够:
  1. 在根目录的 package.json 中定义版本目录
  2. 使用简洁的 catalog: 协议引用这些版本
  3. 仅需修改一个地方即可同时更新所有包
这在需要多个包使用相同关键依赖版本的大型 monorepo 中尤其有用。

如何使用目录

目录结构示例

假设有如下结构的 monorepo:
my-monorepo/
├── package.json
├── bun.lock
└── packages/
    ├── app/
    │   └── package.json
    ├── ui/
    │   └── package.json
    └── utils/
        └── package.json

1. 在根目录 package.json 中定义目录

在根目录的 package.json 中,在 workspaces 对象内添加 catalogcatalogs 字段:
package.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"
      }
    }
  }
}
如果你将 catalogcatalogs 放在 package.json 的顶层,也同样有效。

2. 在工作区包中引用目录版本

在工作区包中,使用 catalog: 协议引用版本:
packages/app/package.json
{
  "name": "app",
  "dependencies": {
    "react": "catalog:",
    "react-dom": "catalog:",
    "jest": "catalog:testing"
  }
}
packages/ui/package.json
{
  "name": "ui",
  "dependencies": {
    "react": "catalog:",
    "react-dom": "catalog:"
  },
  "devDependencies": {
    "jest": "catalog:testing",
    "testing-library": "catalog:testing"
  }
}

3. 运行 Bun Install

运行 bun install,即可根据目录中定义的版本安装所有依赖。

Catalog 与 Catalogs 的区别

Bun 支持两种定义目录的方式:
  1. catalog(单数):用于常用依赖的单一默认目录
    package.json
    "catalog": {
      "react": "^19.0.0",
      "react-dom": "^19.0.0"
    }
    
    使用时仅需写 catalog:
    packages/app/package.json
    "dependencies": {
      "react": "catalog:"
    }
    
  2. catalogs(复数):用于分组依赖的多个命名目录
    package.json
    "catalogs": {
      "testing": {
        "jest": "30.0.0"
      },
      "ui": {
        "tailwind": "4.0.0"
      }
    }
    
    使用时需要指定目录名,格式为 catalog:<name>
    packages/app/package.json
    "dependencies": {
      "jest": "catalog:testing",
      "tailwind": "catalog:ui"
    }
    

使用目录的好处

  • 一致性:确保所有包使用相同版本的关键依赖
  • 维护方便:只需在一个地方更新依赖版本,而非多个 package.json
  • 清晰明了:明确表示哪些依赖在整个 monorepo 中统一使用
  • 简单易用:无需复杂的版本解析策略或外部工具

真实示例

以下是一个针对 React 应用的更完整示例: 根目录 package.json
package.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"
  }
}
packages/app/package.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"
  }
}
packages/ui/package.json
{
  "name": "@monorepo/ui",
  "dependencies": {
    "react": "catalog:",
    "react-dom": "catalog:"
  },
  "devDependencies": {
    "jest": "catalog:testing",
    "react-testing-library": "catalog:testing"
  }
}
packages/utils/package.json
{
  "name": "@monorepo/utils",
  "dependencies": {
    "react": "catalog:"
  },
  "devDependencies": {
    "jest": "catalog:testing"
  }
}

更新版本

要更新所有包的版本,只需修改根目录 package.json 中的版本:
package.json
"catalog": {
  "react": "^19.1.0",  // 从 ^19.0.0 更新
  "react-dom": "^19.1.0"  // 从 ^19.0.0 更新
}
然后运行 bun install 即可更新所有包。

锁文件集成

Bun 的锁文件会跟踪目录版本,确保不同环境中的安装一致。锁文件包含:
  • package.json 中的目录定义
  • 每个目录依赖的解析结果
bun.lock(excerpt)
{
  "lockfileVersion": 1,
  "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": {
    ...
  }
}

限制与注意事项

  • 目录引用必须匹配 catalog 或某个命名 catalogs 中定义的依赖
  • 目录名称中的空字符串和空白字符会被忽略(视为默认目录)
  • 目录中的无效依赖版本会导致 bun install 解析失败
  • 目录仅在工作区内有效,无法在 monorepo 外使用
Bun 的目录系统提供了一种强大且简洁的方式,在 monorepo 中保持依赖版本一致,同时不增加额外的复杂度。

发布

当你运行 bun publishbun pm pack 时,Bun 会自动将 package.json 中的 catalog: 引用替换为具体的版本号。发布的包中包含标准的 semver 版本字符串,不再依赖你的目录定义。