自動安裝
Bun 的自動包安裝功能,用於獨立指令碼執行
如果 Bun 在工作目錄或其上級目錄中找不到 node_modules 目錄,它會放棄 Node.js 風格的模組解析,轉而使用 Bun 模組解析演算法。
在 Bun 風格的模組解析中,Bun 會在執行期間將每個匯入的包自動安裝到全域性模組快取中。 bun install 使用相同的快取。
import { foo } from "foo"; // 安裝 `latest` 版本
foo();
首次執行此指令碼時,Bun 會自動安裝 "foo" 並將其快取。之後的執行會使用快取的版本。
版本解析
Bun 按照以下方式確定要安裝的版本:
- 檢查專案根目錄中是否存在
bun.lock檔案。如果存在,則使用鎖檔案中指定的版本。 - 否則,向上遍歷目錄查詢包含
"foo"作為相依項的package.json檔案。如果找到,則使用指定的語義版本或版本範圍。 - 否則,使用
latest。
快取行為
一旦 Bun 確定了一個版本或版本範圍,它會:
- 檢查模組快取中是否存在相容版本。如果存在,則使用該版本。
- 解析
latest時,檢查package@latest是否在過去 24 小時 內下載並快取過。如果是,則使用該版本。 - 否則,從
npm登錄檔下載並安裝適當的版本。
安裝
Bun 會將包安裝並快取到 <cache>/<pkg>@<version>,因此可以同時快取同一個包的多個版本。它還會在 <cache>/<pkg>/<version> 下建立一個符號連結,以加快查詢包的所有快取版本的速度。
版本說明符
要完全繞過版本解析,請直接在匯入語句中指定版本或版本範圍。
import { z } from "zod@3.0.0"; // 指定版本
import { z } from "zod@next"; // npm 標籤
import { z } from "zod@^3.20.0"; // 語義版本範圍
優勢
- 空間效率 — 每個相依版本在磁碟上僅存在一份。與每個專案重複安裝相比,這樣可以節省空間和時間。
- 可移植性 — 原始檔是_自包含的_,因此分享指令碼和程式碼片段時,不必將程式碼和設定檔目錄壓縮成 zip。藉助
import語句中的版本指定符,甚至不需要package.json。 - 便利性 — 使用
bun run執行檔案或指令碼前,無需執行npm install或bun install。 - 向後相容性 — 由於 Bun 仍會遵循
package.json中指定的版本(如果存在),因此只需一條命令即可切換到 Bun 風格的解析方式:rm -rf node_modules。
限制
- 無 IntelliSense。IDE 中的 TypeScript 自動補全相依於
node_modules內的型別宣告檔案。我們正在研究解決方案。 - 不支援 patch-package
常見問題解答
這與 pnpm 的做法有何不同?
使用 pnpm,必須先執行 pnpm install,該命令會建立一個包含符號連結的 node_modules 資料夾供執行環境解析。相比之下,Bun 在執行檔案時動態解析相依,無需事先執行任何安裝命令。Bun 也不會建立 node_modules 資料夾。
這與 Yarn Plug'N'Play 的做法有何不同?
使用 Yarn,必須先執行 yarn install,才能執行指令碼。相比之下,Bun 會在執行檔案時動態解析相依;無需事先執行任何 install 命令。
Yarn Plug'N'Play 使用 zip 檔案儲存相依,這導致相依載入在執行環境更慢,因為對 zip 檔案的隨機訪問通常比等效的磁碟查詢更慢。參考
這與 Deno 有何區別?
Deno 要求在每個 npm import 前使用 npm: 說明符,不支援通過 tsconfig.json 中的 compilerOptions.paths 使用匯入對映,並且對 package.json 設定的支援尚不完整。與 Deno 不同,Bun 目前不支援 URL 匯入。