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

觀察模式

Bun 中的自動過載,支援 --watch 和 --hot 模式

Bun 支援兩種自動過載方式:

  • --watch 模式:當匯入的檔案發生更改時,Bun 會硬重啟行程。
  • --hot 模式:當匯入的檔案發生更改時,Bun 會軟過載程式碼(不重啟行程)。

--watch 模式

觀察模式可與 bun test 和 bun build 配合使用,也可用於執行 TypeScript、JSX 和 JavaScript 檔案。

在 --watch 模式下執行檔案:

terminal
bun --watch index.tsx

在 --watch 模式下執行測試:

terminal
bun --watch test

在 --watch 模式下,Bun 會跟蹤所有匯入的檔案並監視它們的變化。當檔案發生變化時,Bun 會使用與初始執行相同的 CLI 引數和環境變數重新啟動行程。如果 Bun 崩潰,--watch 會嘗試重新啟動行程。

以下範例展示了 Bun 如何在你編輯檔案時即時過載檔案,並且 VSCode 已設定為每次按鍵時儲存檔案。

terminal
bun run --watch watchy.tsx
watchy.tsx
import { serve } from "bun";

console.log("我在此時重啟:", Date.now());

serve({
  port: 4003,
  fetch(request) {
    return new Response("Sup");
  },
});

bun watch 動圖

啟用 save-on-keypress 後,在 watch 模式下執行 bun test:

terminal
bun --watch test

bun test 動圖


--hot 模式

使用 bun --hot 在使用 Bun 執行程式碼時啟用熱過載。與 --watch 模式不同,Bun 不會完全重啟整個行程。它會檢測程式碼變化,並使用新程式碼更新其內部模組快取。

terminal
bun --hot server.ts

以入口檔案(本例中為 server.ts)為起點,Bun 會建置一個包含所有匯入原始檔(不包括 node_modules 中的檔案)的登錄檔,並監視這些檔案的變化。當檔案發生變化時,Bun 會執行“軟過載”。Bun 會重新求值所有檔案,但全域性狀態(尤其是 globalThis 物件)會保留。

server.ts
// 讓 TypeScript 不報錯
declare global {
  var count: number;
}

globalThis.count ??= 0;
console.log(`過載了 ${globalThis.count} 次`);
globalThis.count++;

// 防止 `bun run` 退出
setInterval(function () {}, 1000000);

如果你用 bun --hot server.ts 執行這個檔案,每次儲存檔案時你都會看到過載計數遞增。

terminal
bun --hot server.ts
Text
Reloaded 0 times
Reloaded 1 times
Reloaded 2 times

像 nodemon 這樣的傳統檔案監視器會重啟整個行程,因此 HTTP 伺服器和其他有狀態物件都會丟失。相比之下,bun --hot 無需重啟行程即可反映更新後的程式碼。

HTTP 伺服器

你可以更新 HTTP 請求處理器,而無需關閉伺服器:儲存檔案時,Bun 會使用更新後的程式碼重新載入伺服器,同時不會重啟行程。因此可以實現極快的重新整理速度。

server.ts
globalThis.count ??= 0;
globalThis.count++;

Bun.serve({
  fetch(req: Request) {
    return new Response(`過載了 ${globalThis.count} 次`);
  },
  port: 3000,
});
實現細節

熱過載時,Bun 會:

  • 重置內部的 require 快取和 ES 模組登錄檔(Loader.registry)
  • 同步執行垃圾回收(以減少記憶體洩漏,但會犧牲一定執行環境效能)
  • 重新從頭轉譯所有程式碼(包括源對映)
  • 使用 JavaScriptCore 重新求值程式碼

目前的實現並非特別最佳化,會重新轉譯未發生變化的檔案,也沒有嘗試增量編譯。這只是一個起點。