Skip to main content
Bun 支持通过 CLI 标志实现两种自动重载:
  • --watch 模式:当导入的文件发生更改时,Bun 会硬重启进程。
  • --hot 模式:当导入的文件发生更改时,Bun 会软重载代码(不重启进程)。

--watch 模式

观察模式可以用于 bun test 或运行 TypeScript、JSX 和 JavaScript 文件时。 --watch 模式下运行文件:
terminal
bun --watch index.tsx
--watch 模式下运行测试:
terminal
bun --watch test
--watch 模式下,Bun 会跟踪所有导入的文件并监视它们的更改。当检测到更改时,Bun 会重启进程,保持初始运行时使用的相同 CLI 参数和环境变量。如果 Bun 崩溃,--watch 会尝试自动重启进程。
⚡️ 重载非常快。 你可能习惯的文件系统监听器通常通过多层库来封装本地 API,或者更糟的是,依赖于轮询。相反,Bun 使用操作系统本地的文件系统监听 API,如 kqueue 或 inotify 来检测文件变化。Bun 还做了许多优化以支持更大规模的项目(比如设置较高的文件描述符 rlimit、静态分配文件路径缓冲区、尽可能重用文件描述符等)。
以下示例演示了 Bun 在编辑文件时的实时重载,VSCode 被配置为每次按键保存文件
terminal
bun run --watch watchy.tsx
https://mintcdn.com/ikxin/RzFFGbzo0-4huILA/icons/typescript.svg?fit=max&auto=format&n=RzFFGbzo0-4huILA&q=85&s=a3dffd2241f05776d3bd25171d0c5a79watchy.tsx
import { serve } from "bun";

console.log("我在此时重启:", Date.now());

serve({
  port: 4003,
  fetch(request) {
    return new Response("Sup");
  },
});
在此示例中,Bun 运行的效果如下:
bun watch gif
在启用了 save-on-keypress 的情况下运行 bun test 的观察模式:
terminal
bun --watch test
bun test gif
--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 不会硬重启整个进程,而是检测代码变化并用新代码更新内部模块缓存。
这不同于浏览器中的热重载!很多框架提供 “热重载” 功能,可以编辑并保存前端代码(比如 React 组件),浏览器页面无需刷新即可看到变更。Bun 的 --hot 是这种体验在服务器端的对应实现。想要浏览器端的热重载,可以使用像 Vite 这样的框架。
terminal
bun --hot server.ts
从入口文件(上例中的 server.ts)开始,Bun 会构建所有导入源文件(排除 node_modules 中的文件)注册表并监视这些文件的变化。发现变化时,Bun 会执行 “软重载”。所有文件都重新求值,但所有全局状态(特别是 globalThis 对象)都会被保留。
https://mintcdn.com/ikxin/RzFFGbzo0-4huILA/icons/typescript.svg?fit=max&auto=format&n=RzFFGbzo0-4huILA&q=85&s=a3dffd2241f05776d3bd25171d0c5a79server.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 index.ts
重载了 1 次
重载了 2 次
重载了 3 次
传统的文件观察器如 nodemon 会重启整个进程,因此 HTTP 服务器和其他有状态对象都会丢失。相比之下,bun --hot 能够在不重启进程的情况下反映代码更新。

HTTP 服务器

这使得你可以更新 HTTP 请求处理函数,而无需关闭服务器本身。保存文件后,HTTP 服务器会用更新后的代码重新加载,进程不会重启。这带来了非常快的刷新速度。
https://mintcdn.com/ikxin/RzFFGbzo0-4huILA/icons/typescript.svg?fit=max&auto=format&n=RzFFGbzo0-4huILA&q=85&s=a3dffd2241f05776d3bd25171d0c5a79server.ts
globalThis.count ??= 0;
globalThis.count++;

Bun.serve({
  fetch(req: Request) {
    return new Response(`重载了 ${globalThis.count} 次`);
  },
  port: 3000,
});
注意 — 在未来版本的 Bun 中,计划支持 Vite 的 import.meta.hot,以便实现更好的生命周期管理和与生态系统的兼容。
热重载时,Bun 会:
  • 重置内部的 require 缓存和 ES 模块注册表(Loader.registry
  • 同步运行垃圾回收(以减少内存泄漏,但会牺牲一定运行时性能)
  • 重新从头转译所有代码(包括 sourcemaps)
  • 使用 JavaScriptCore 重新求值代码
目前的实现并非特别优化,会重新转译未发生变化的文件,也没有尝试增量编译。这只是一个起点。