Skip to content

Bun 通过 CLI 标志支持两种自动重新加载:

  • --watch 模式,当导入的文件更改时硬重启 Bun 的进程。
  • --hot 模式,当导入的文件更改时软重新加载代码(不重启进程)。

--watch 模式

监听模式可以与 bun test 一起使用,或在运行 TypeScript、JSX 和 JavaScript 文件时使用。

要以 --watch 模式运行文件:

bash
bun --watch index.tsx

要以 --watch 模式运行测试:

bash
bun --watch test

--watch 模式下,Bun 跟踪所有导入的文件并监视它们的更改。当检测到更改时,Bun 重启进程,保留初始运行中使用的相同 CLI 参数和环境变量集。如果 Bun 崩溃,--watch 将尝试自动重启进程。

NOTE

⚡️ 重新加载很快。 你可能习惯的文件系统监听器有几层库包装原生 API,或者更糟,依赖轮询。

相反,Bun 使用操作系统原生文件系统监听器 API(如 kqueue 或 inotify)来检测文件更改。Bun 还做了许多优化,使其能够扩展到更大的项目(例如为文件描述符设置高 rlimit,静态分配文件路径缓冲区,尽可能重用文件描述符等)。

以下示例显示 Bun 在编辑文件时实时重新加载文件,VSCode 配置为 每次按键时保存

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

console.log("I restarted at:", Date.now());

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

在这个示例中,Bun

以监听模式运行 bun test 并启用 save-on-keypress

bash
bun --watch test

NOTE

**`--no-clear-screen`** 标志在你不希望终端清空的场景中很有用,例如使用 `concurrently` 等工具同时运行多个 `bun build --watch` 命令时。没有这个标志,一个实例的输出可能会清除其他实例的输出,可能会将来自一个实例的错误隐藏在另一个实例的输出之下。`--no-clear-screen` 标志类似于 TypeScript 的 `--preserveWatchOutput`,可以防止这个问题。它可以与 `--watch` 组合使用,例如:`bun build --watch --no-clear-screen`。

--hot 模式

使用 bun --hot 在与 Bun 一起执行代码时启用热重新加载。这与 --watch 模式不同,因为 Bun 不会硬重启整个进程。相反,它检测代码更改并使用新代码更新其内部模块缓存。

NOTE

这与浏览器中的热重新加载不同!许多框架提供"热重新加载"体验,你可以编辑和保存前端代码(比如 React 组件)并在浏览器中看到更改而无需刷新页面。Bun 的 `--hot` 是这种体验的服务器端等效。要在浏览器中获得热重新加载,使用像 [Vite](https://vite.dev) 这样的框架。
bash
bun --hot server.ts

从入口点(上面示例中的 server.ts)开始,Bun 构建所有导入的源文件(不包括 node_modules 中的文件)的注册表并监视它们的更改。当检测到更改时,Bun 执行"软重新加载"。所有文件都被重新评估,但所有全局状态(特别是 globalThis 对象)都被保留。

ts
// 让 TypeScript 开心
declare global {
  var count: number;
}

globalThis.count ??= 0;
console.log(`Reloaded ${globalThis.count} times`);
globalThis.count++;

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

如果你用 bun --hot server.ts 运行这个文件,你会看到每次保存文件时重新加载计数递增。

bash
bun --hot index.ts
txt
Reloaded 1 times
Reloaded 2 times
Reloaded 3 times

传统的文件监听器如 nodemon 重启整个进程,所以 HTTP 服务器和其他有状态对象会丢失。相比之下,bun --hot 能够在不重启进程的情况下反映更新的代码。

HTTP 服务器

例如,这使得可以在不关闭服务器本身的情况下更新 HTTP 请求处理程序。当你保存文件时,你的 HTTP 服务器将使用更新的代码重新加载,而进程不会被重启。这导致非常快的刷新速度。

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

Bun.serve({
  fetch(req: Request) {
    return new Response(`Reloaded ${globalThis.count} times`);
  },
  port: 3000,
});

NOTE

**注意** — 在未来版本的 Bun 中,计划支持 Vite 的 `import.meta.hot` 以更好地管理热重新加载的生命周期并与生态系统保持一致。

实现细节">

在热重新加载时,Bun:

  • 重置内部 require 缓存和 ES 模块注册表(Loader.registry
  • 同步运行垃圾回收器(以最小化内存泄漏,以运行时性能为代价)
  • 从头开始重新转译所有代码(包括 sourcemaps)
  • 用 JavaScriptCore 重新评估代码

这个实现还没有特别优化。它重新转译未更改的文件。它没有尝试增量编译。这是一个起点。

Bun学习网由www.bunjs.com.cn整理维护