觀察模式
Bun 中的自動過載,支援 --watch 和 --hot 模式
Bun 支援兩種自動過載方式:
--watch模式:當匯入的檔案發生更改時,Bun 會硬重啟行程。--hot模式:當匯入的檔案發生更改時,Bun 會軟過載程式碼(不重啟行程)。
--watch 模式
觀察模式可與 bun test 和 bun build 配合使用,也可用於執行 TypeScript、JSX 和 JavaScript 檔案。
在 --watch 模式下執行檔案:
bun --watch index.tsx
在 --watch 模式下執行測試:
bun --watch test
在 --watch 模式下,Bun 會跟蹤所有匯入的檔案並監視它們的變化。當檔案發生變化時,Bun 會使用與初始執行相同的 CLI 引數和環境變數重新啟動行程。如果 Bun 崩潰,--watch 會嘗試重新啟動行程。
以下範例展示了 Bun 如何在你編輯檔案時即時過載檔案,並且 VSCode 已設定為每次按鍵時儲存檔案。
bun run --watch watchy.tsx
import { serve } from "bun";
console.log("我在此時重啟:", Date.now());
serve({
port: 4003,
fetch(request) {
return new Response("Sup");
},
});

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

--hot 模式
使用 bun --hot 在使用 Bun 執行程式碼時啟用熱過載。與 --watch 模式不同,Bun 不會完全重啟整個行程。它會檢測程式碼變化,並使用新程式碼更新其內部模組快取。
bun --hot server.ts
以入口檔案(本例中為 server.ts)為起點,Bun 會建置一個包含所有匯入原始檔(不包括 node_modules 中的檔案)的登錄檔,並監視這些檔案的變化。當檔案發生變化時,Bun 會執行“軟過載”。Bun 會重新求值所有檔案,但全域性狀態(尤其是 globalThis 物件)會保留。
// 讓 TypeScript 不報錯
declare global {
var count: number;
}
globalThis.count ??= 0;
console.log(`過載了 ${globalThis.count} 次`);
globalThis.count++;
// 防止 `bun run` 退出
setInterval(function () {}, 1000000);
如果你用 bun --hot server.ts 執行這個檔案,每次儲存檔案時你都會看到過載計數遞增。
bun --hot server.ts
Reloaded 0 times
Reloaded 1 times
Reloaded 2 times
像 nodemon 這樣的傳統檔案監視器會重啟整個行程,因此 HTTP 伺服器和其他有狀態物件都會丟失。相比之下,bun --hot 無需重啟行程即可反映更新後的程式碼。
HTTP 伺服器
你可以更新 HTTP 請求處理器,而無需關閉伺服器:儲存檔案時,Bun 會使用更新後的程式碼重新載入伺服器,同時不會重啟行程。因此可以實現極快的重新整理速度。
globalThis.count ??= 0;
globalThis.count++;
Bun.serve({
fetch(req: Request) {
return new Response(`過載了 ${globalThis.count} 次`);
},
port: 3000,
});
實現細節
熱過載時,Bun 會:
- 重置內部的
require快取和 ES 模組登錄檔(Loader.registry) - 同步執行垃圾回收(以減少記憶體洩漏,但會犧牲一定執行環境效能)
- 重新從頭轉譯所有程式碼(包括源對映)
- 使用 JavaScriptCore 重新求值程式碼
目前的實現並非特別最佳化,會重新轉譯未發生變化的檔案,也沒有嘗試增量編譯。這只是一個起點。