執行環境套件管理器打包器測試執行器程式碼檢查格式化指南參考部落格意見回饋

隔離安裝

與 pnpm 方法類似的嚴格相依隔離

Bun 提供了一種名為 隔離安裝 的替代軟體包安裝策略,可建立類似於 pnpm 方法的嚴格相依隔離。此模式可防止幽靈相依(匯入自身未宣告相依的軟體包),並使建置過程可復現且具有確定性。

對於新建的工作區/monorepo 專案(鎖檔案中包含 configVersion = 1),隔離安裝是預設方式。除非進行顯式設定,否則現有專案會繼續使用提升式安裝。

什麼是隔離安裝?

隔離安裝建立了非提升的相依結構,包只能訪問它們顯式宣告的相依。這有別於 npm 和 Yarn 傳統的“提升”安裝策略,即相依項被扁平化到共享的 node_modules 目錄中。

主要優點

  • 防止幻影相依 — 包不能意外匯入未宣告的相依
  • 確定性解析 — 無論安裝了什麼,相依樹相同
  • 更適合多包儲存庫 — 工作區隔離防止包之間的交叉汙染
  • 可復現建置 — 在不同環境下解析行為更可預測。

使用隔離安裝

命令列

使用 --linker 標誌指定安裝策略:

terminal
# 使用隔離安裝
bun install --linker isolated

# 使用傳統提升安裝
bun install --linker hoisted

設定檔

在你的 bunfig.toml 或全域性 $HOME/.bunfig.toml 中設定預設 linker 策略:

bunfig.toml
[install]
linker = "isolated"

預設行為

預設 linker 策略取決於專案鎖檔案的 configVersion:

configVersion是否使用工作區?預設 Linker
1✅isolated
1❌hoisted
0✅hoisted
0❌hoisted

新專案:預設為 configVersion = 1。工作區中,v1 預設使用隔離 linker;否則使用提升連結。

已有 Bun 專案(v1.3.2 之前建立):如果現有鎖檔案未標明版本,執行 bun install 時 Bun 會將 configVersion 設為 0,保持之前的提升 linker 預設。

從其他套件管理器遷移:

  • 來自 pnpm:configVersion = 1(工作區中使用隔離安裝)
  • 來自 npm 或 yarn:configVersion = 0(使用提升安裝)

通過傳遞 --linker 標誌或在設定檔中設定來覆蓋預設值。

隔離安裝如何工作

目錄結構

隔離安裝不提升相依,而是建立兩層結構:

tree
node_modules/
├── .bun/                          # Central package store
│   ├── node_modules/              # Hoisted fallback (see install.hoist)
│   │   └── package -> ../package@1.0.0/node_modules/package
│   ├── package@1.0.0/             # Versioned package installations
│   │   └── node_modules/
│   │       └── package/           # 實際包檔案
│   ├── @scope+package@2.1.0/      # 作用域包 (+ 代替 /)
│   │   └── node_modules/
│   │       └── @scope/
│   │           └── package/
│   └── ...
└── package-name -> .bun/package@1.0.0/node_modules/package  # 符號連結

儲存目錄名稱中 @ 之後的部分是包的解析標識。對於登錄檔包,該部分是其版本號。對於資料夾、tarball、git 或 GitHub 相依,Bun 會根據路徑或 URL(以及提交)生成該部分,因此長度可能很長。Bun 最多寫入其中的 80 個位元組:如果解析標識較長,就將其截斷到最多 63 個位元組,然後附加 + 和根據完整解析標識生成的 16 個十六進位制數字。因此,儲存中包的路徑最多比專案目錄長 34 + 2 * <name length> + 80 個字元(如果包有 peer 相依,則再多 17 個字元)。這在 Windows 上很重要:超過 260 個字元的路徑仍可供 Bun 本身使用,但不能作為包生命週期指令碼的工作目錄。

解析演算法

  1. 中央儲存 — Bun 將所有包安裝到 node_modules/.bun/package@version/ 目錄中
  2. 符號連結 — 頂層 node_modules 包含指向中央儲存的符號連結
  3. Peer 解析 — 複雜的 peer 相依會建立專用目錄名稱
  4. 去重 — 具有相同包 ID 和 peer 相依集的包會被共享
  5. 重新連結 — 後續安裝時,如果某個相依被重新解析,Bun 會複用現有儲存條目並重新指向其符號連結。不再被引用的儲存條目會保留,直到執行 bun prune

工作區處理

在 monorepo 中,Bun 會以特殊方式處理工作區相依:

  • 工作區包 — 直接連結到其源目錄,而不是儲存目錄
  • 工作區相依 — 可以訪問 monorepo 中的其他工作區包
  • 外部相依 — 安裝在隔離儲存中

與提升安裝的比較

方面提升(npm/Yarn)隔離(類似 pnpm)
相依訪問包可訪問任何提升的相依包只能看到宣告的相依
幻影相依❌ 可能發生✅ 防止
磁碟使用✅ 較低(共享安裝)✅ 類似(使用符號連結)
確定性❌ 較低✅ 更高
Node.js 相容性✅ 標準行為✅ 通過符號連結相容
適用場景單專案,舊程式碼多包儲存庫,嚴格相依管理

高階功能

對等相依處理

隔離安裝會將對等相依編碼到儲存路徑中:

tree
# 有 peer 相依的包建立特化路徑
node_modules/.bun/package@1.0.0_react@18.2.0/

目錄名稱同時包含包版本及其對等相依版本,因此每種唯一組合都會獲得自己的安裝。

使用 install.hoist = false 進行嚴格解析

預設情況下,Bun 會建立 node_modules/.bun/node_modules,這是一個回退目錄,其中包含指向每個已安裝包的符號連結。由於此目錄是每個儲存條目的祖先目錄,儲存中的包可以解析它從未宣告的相依。設定 install.hoist = false(或在 .npmrc 中設定 hoist=false,與 pnpm 一致)即可跳過此目錄的建立。此後,未宣告的匯入會失敗,而不會相依恰好安裝的其他包。這裡有一個與 pnpm 相同的注意事項:根 node_modules 也位於儲存目錄之上。因此,連結到該目錄中的包(你的直接相依、匹配 publicHoistPattern 的包,以及工作區包)仍可從任何儲存包中解析:

bunfig.toml
[install]
linker = "isolated"
hoist = false

install.hoistPattern 和 install.publicHoistPattern 分別提供了基於模式控制同一回退目錄和根 node_modules 的方式。

全域性虛擬儲存

啟用 install.globalStore 後,Bun 會將儲存條目一次性物化到 <cache>/links/ 下的全域性虛擬儲存中,而 node_modules/.bun/<pkg>@<ver> 則是指向該儲存的符號連結。在典型的中型專案中,執行 rm -rf node_modules 後進行熱安裝,每個包只需建立一個符號連結,而無需再次複製每個包的所有檔案,速度大約快 7 倍。全域性儲存預設關閉;有關如何啟用、完整佈局、基準測試和權衡,請參閱全域性儲存文件。

後端策略

當全域性儲存被停用(預設)或某個條目不適合使用時,Bun 會使用以下方式之一將條目物化到專案中:

  • Clonefile(macOS)— 寫時複製檔案系統克隆
  • Hardlink(Linux/Windows)— 用於節省磁碟空間的硬連結
  • Copyfile(回退方案)— 在其他方法不可用時複製完整檔案

除錯隔離安裝

啟用詳細日誌記錄以檢視安裝過程:

terminal
bun install --linker isolated --verbose

詳細輸出會顯示:

  • 儲存條目建立
  • 符號連結操作
  • 對等相依解析
  • 去重決策

故障排除

相容性問題

一些包可能不相容隔離安裝,原因包括:

  • 硬編碼路徑 — 假設 node_modules 結構扁平
  • 動態匯入 — 執行環境匯入不遵循 Node.js 解析
  • 建置工具 — 直接掃描 node_modules

遇到問題時可:

  1. 對特定專案切換回提升模式:

    terminal
    bun install --linker hoisted
    
  2. 報告相容性問題,幫助改進隔離安裝支援

效能考慮

  • 安裝時間 — 可能略慢,因符號連結操作
  • 磁碟使用 — 與提升類似(使用符號連結,不復制檔案)
  • 記憶體使用 — 因複雜 peer 解析,安裝時更高。

遷移指南

從 npm/Yarn 遷移

terminal
# 刪除現有 node_modules 和鎖檔案
rm -rf node_modules package-lock.json yarn.lock

# 使用隔離 linker 安裝
bun install --linker isolated

從 pnpm 遷移

隔離安裝在概念上與 pnpm 類似,因此遷移是直接的:

terminal
# 刪除 pnpm 檔案
rm -rf node_modules pnpm-lock.yaml

# 使用 Bun 的隔離 linker 安裝
bun install --linker isolated

這些佈局很相似:Bun 會將包從其全域性快取硬連結(在 macOS 上則克隆)到每個專案的儲存目錄 node_modules/.bun/,並將頂層 node_modules 條目符號連結到該目錄。啟用 install.globalStore 後,這些儲存條目會改為符號連結到全域性虛擬儲存。

何時使用隔離安裝

適合使用隔離安裝的情況:

  • 在多包儲存庫中工作
  • 需要嚴格相依管理
  • 需要防止幻影相依
  • 建置需相依確定性的庫

適合使用提升安裝的情況:

  • 處理假設 node_modules 扁平的舊程式碼
  • 需要相容現有建置工具
  • 在符號連結支援不佳的環境中工作
  • 偏好傳統的 npm 行為

相關文件