工作區
開發包含多個獨立包的複雜多包儲存庫(monorepo)
Bun 支援在 package.json 中設定 workspaces。藉助工作區,你可以在單個儲存庫中開發多個獨立的包,這種儲存庫稱為 monorepo。
多包儲存庫通常具有以下結構:
<root>
├── README.md
├── bun.lock
├── package.json
├── tsconfig.json
└── packages
├── pkg-a
│ ├── index.ts
│ ├── package.json
│ └── tsconfig.json
├── pkg-b
│ ├── index.ts
│ ├── package.json
│ └── tsconfig.json
└── pkg-c
├── index.ts
├── package.json
└── tsconfig.json
根目錄 package.json 中的 "workspaces" 鍵列出了要作為工作區處理的子目錄。按照慣例,這些目錄位於名為 packages 的目錄中。
{
"name": "my-project",
"version": "1.0.0",
"workspaces": ["packages/*"],
"devDependencies": {
"example-package-in-monorepo": "workspace:*"
}
}
{
"name": "my-project",
"version": "1.0.0",
"workspaces": ["packages/**", "!packages/**/test/**", "!packages/**/template/**"]
}
每個工作區都有自己的 package.json。要引用多包儲存庫中的另一個包,請在 package.json 中將 semver 範圍或工作區協議(例如 workspace:*)用作版本。
{
"name": "pkg-a",
"version": "1.0.0",
"dependencies": {
"pkg-b": "workspace:*"
}
}
bun install 會為多包儲存庫中的所有工作區安裝相依,並在可能的情況下對包進行去重。若只想為特定工作區安裝相依,請使用 --filter 標誌。
# 安裝所有以 `pkg-` 開頭且不包含 `pkg-c` 的工作區相依
bun install --filter "pkg-*" --filter "!pkg-c"
# 也可以使用路徑,這與上面命令效果相同。
bun install --filter "./packages/pkg-*" --filter "!pkg-c" # 或 --filter "!./packages/pkg-c"
釋出時,Bun 會將 workspace: 版本替換為包的 package.json 版本:
"workspace:*" -> "1.0.1"
"workspace:^" -> "^1.0.1"
"workspace:~" -> "~1.0.1"
指定的版本優先於包 package.json 中的版本:
"workspace:1.0.2" -> "1.0.2" // 即使當前版本是 1.0.1
工作區有幾個主要優點。
- 將程式碼拆分為邏輯部分。 如果一個包相依於另一個包,請在
package.json中將其新增為相依項。如果包b相依於a,bun install會將本地packages/a目錄安裝到node_modules,而不是從 npm 登錄檔下載它。 - Bun 可以對相依進行去重。 如果
a和b共享一個相依,Bun 會將它_提升_到根目錄的node_modules目錄。這可以節省磁碟空間,並儘可能避免同時安裝同一個包的多個版本所導致的“相依地獄”。 - 在多個包中執行指令碼。 使用
--filter標誌 一次在多個包中執行package.json指令碼,或使用--workspaces在所有工作區中執行指令碼。
自包含工作區
使用提升式連結器時,多個工作區共享的相依會被提升到根目錄的 node_modules。有些工具無法處理這種情況:Electron 打包器和無伺服器打包器會遍歷、精簡併重新打包_單個工作區_的 node_modules,並期望每個相依都實際存在於該目錄下。可以在此類工作區的 package.json 中將其標記為自包含(使用 Yarn 所用的相同鍵;只有 "workspaces" 的值會改變佈局):
{
"name": "desktop",
"installConfig": { "hoistingLimits": "workspaces" }
}
也可以在根目錄的 package.json 中,緊挨著工作區 glob 的位置進行設定:
{
"workspaces": {
"packages": ["apps/*", "packages/*"],
"selfContained": ["apps/desktop"]
}
}
(條目可以是工作區路徑或包名稱)
對於該工作區,bun install 會將其視為提升屏障——它直接或間接相依的所有內容(包括通過它所相依的其他工作區引入的內容)都不會被放置在 apps/desktop/node_modules 之上,因此該目錄包含完整的相依樹;這些包會以實際副本的形式安裝,而不是從快取建立硬連結/克隆,因此重寫這些包的工具不會影響快取或其他專案。其他所有工作區仍會像往常一樣將相依提升到根目錄。鎖檔案不會記錄此設定。Bun 每次安裝時都會從 package.json 中讀取該設定,包括使用 --frozen-lockfile 時,因此無論是否啟用此設定,鎖檔案都相同。此設定對隔離式連結器無效,因為在該模式下,每個包本來就只會解析自身的相依。
使用 Catalogs 共享版本
當許多軟體包需要使用相同的相依版本時,請在根目錄的 package.json 中的 catalog 裡統一定義這些版本,然後在工作區中通過 catalog: 協議引用它們。更新 catalog 會同步更新所有引用它的軟體包。請參閱 Catalogs。