目錄
在 monorepo 中跨多個包共享通用相依版本
目錄可在 monorepo 中的各個包之間共享相依版本。無需在每個工作區包中重複指定相同的版本,只需在根目錄的 package.json 中定義一次,然後在整個專案中引用即可。
概述
無需讓每個工作區軟體包單獨指定自己的版本,你可以:
- 在根目錄的
package.json中定義版本目錄 - 使用
catalog:協議引用這些版本 - 只需在一個地方更改版本,即可一次性更新所有軟體包
目錄在大型 monorepo 中最為重要,因為其中數十個包都相依相同版本的關鍵相依項。
如何使用目錄
目錄結構範例
假設有如下結構的 monorepo:
my-monorepo/
├── package.json
├── bun.lock
└── packages/
├── app/
│ └── package.json
├── ui/
│ └── package.json
└── utils/
└── package.json
1. 在根目錄 package.json 中定義目錄
在根目錄的 package.json 中,在 workspaces 物件內新增 catalog 或 catalogs 欄位:
{
"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 和 catalogs 也可以在 package.json 的頂層使用。
2. 在工作區包中引用目錄版本
在工作區包中,使用 catalog: 協議引用版本:
{
"name": "app",
"dependencies": {
"react": "catalog:",
"react-dom": "catalog:",
"jest": "catalog:testing"
}
}
{
"name": "ui",
"dependencies": {
"react": "catalog:",
"react-dom": "catalog:"
},
"devDependencies": {
"jest": "catalog:testing",
"testing-library": "catalog:testing"
},
"peerDependencies": {
"react": "catalog:"
}
}
catalog: 引用可在 dependencies、devDependencies、optionalDependencies、peerDependencies 中使用,也可作為根目錄 overrides 規則的值使用。目錄引用的行為與直接內聯目錄範圍完全相同。
3. 執行 Bun Install
執行 bun install,即可根據目錄中定義的版本安裝所有相依。
Catalog 與 Catalogs 的區別
Bun 支援兩種定義目錄的方式:
-
catalog(單數):用於常用相依的單一預設目錄package.json"catalog": { "react": "^19.0.0", "react-dom": "^19.0.0" }使用
catalog:引用:packages/app/package.json"dependencies": { "react": "catalog:" } -
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
{
"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"
}
}
{
"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"
}
}
{
"name": "@monorepo/ui",
"dependencies": {
"react": "catalog:",
"react-dom": "catalog:"
},
"devDependencies": {
"jest": "catalog:testing",
"react-testing-library": "catalog:testing"
}
}
{
"name": "@monorepo/utils",
"dependencies": {
"react": "catalog:"
},
"devDependencies": {
"jest": "catalog:testing"
}
}
更新版本
要在所有包中更新版本,只需在根目錄 package.json 中更改版本:
"catalog": {
"react": "^19.1.0", // 從 ^19.0.0 更新
"react-dom": "^19.1.0" // 從 ^19.0.0 更新
}
然後執行 bun install 即可更新所有包。
使用 bun add 新增到目錄
bun add --catalog 會將條目新增到根目錄目錄中,並在當前包中寫入 "catalog:";--catalog=<name> 會將條目新增到 catalogs.<name> 中,並寫入 "catalog:<name>"。除非傳入顯式版本,否則 Bun 會重複使用現有目錄條目。參見 bun add --catalog。
即使不使用該標誌,bun add react(不帶版本)也會在預設目錄已列出 react 時寫入 "catalog:"。傳入版本則會改為寫入具體的範圍。
鎖檔案整合
Bun 的鎖檔案會跟蹤目錄版本,因此可以確保不同環境中的安裝結果一致。鎖檔案包含:
- package.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": {
...
}
}
限制與注意事項
- 目錄引用必須對應
catalog或某個命名catalogs中定義的相依項 - Bun 會忽略目錄名稱中的空字串和空白字元,並將其視為預設目錄
catalog:default與catalog:相同。你可以通過catalog或catalogs.default定義預設目錄,但同一個包同時列在兩者中會報錯- 目錄中的無效相依版本會導致
bun install解析失敗 catalog:僅適用於根目錄和工作區的package.json檔案。在已釋出的包中使用時會導致解析失敗。使用bun publish或bun pm pack釋出,這些命令會將其替換為實際範圍(參見釋出)
釋出
當你執行 bun publish 或 bun pm pack 時,Bun 會將 package.json 中的 catalog: 引用替換為解析後的版本號。釋出的包包含常規的 semver 字串,不再相依你的 catalog 定義。