在使用 Bun 全栈开发服务器时,HMR 默认启用。
import.meta.hot API 参考
Bun 实现了一个客户端 HMR API,参考了 Vite 的 import.meta.hot API。可以用 if (import.meta.hot) 来检测,生产环境中会被 tree-shaking 去除。
HMR API 仍在开发中,一些功能尚未实现。在
Bun.serve 中可以通过设置 development 选项 { hmr: false } 来禁用 HMR。API 方法
| 方法 | 状态 | 说明 |
|---|---|---|
hot.accept() | ✅ | 表示模块支持热更新可以安全替换。 |
hot.data | ✅ | 在模块更新间保持数据状态。 |
hot.dispose() | ✅ | 添加模块即将替换时执行的回调函数。 |
hot.invalidate() | ❌ | |
hot.on() | ✅ | 绑定事件监听器。 |
hot.off() | ✅ | 移除通过 on 绑定的事件监听器。 |
hot.send() | ❌ | |
hot.prune() | 🚧 | 注意:回调目前从未被调用。 |
hot.decline() | ✅ | 无操作函数,匹配 Vite 的 import.meta.hot。 |
import.meta.hot.accept()
accept() 方法指示模块可以进行热替换。当不传入参数调用时,表示该模块可以通过重新评估文件来替换。在热更新之后,对该模块的导入者将会被自动修补。
index.ts 引入的所有文件创建了一个热重载边界。也就是说,只要 foo.ts 或其任何依赖被保存修改,更新会冒泡到 index.ts 并重新执行。随后,导入 index.ts 的文件会被更新补丁,导入新的版本的 getNegativeCount()。如果只有 index.ts 被更新,只有该文件会重新执行,并且 foo.ts 里的计数器会重用。
这可以与 import.meta.hot.data 结合使用,将状态从旧模块传递到新模块。
当没有任何模块调用
import.meta.hot.accept()(也没有 React Fast Refresh 或插件调用它),
文件更新时页面会刷新,并且控制台会显示哪些文件被失效。若你更倾向于使用页面刷新,这个警告可忽略。带回调
如果传入一个回调,import.meta.hot.accept 将像 Vite 那样工作。它不会自动补丁导入者,而是把新模块作为参数调用回调。
接受其它模块
多依赖
undefined。
import.meta.hot.data
import.meta.hot.data 用于在热替换期间在模块实例间持久化状态,从前一个模块传递数据到新模块。当写入 import.meta.hot.data 时,Bun 会同时标记该模块为自接受(相当于调用了 import.meta.hot.accept())。
data 会被内联为 {},因此不能用作状态持有。
import.meta.hot.dispose()
绑定一个销毁回调。该回调在以下时机被调用:- 模块即将被替换(即新模块加载前)
- 模块被卸载(所有对该模块的导入被移除,见
import.meta.hot.prune())
import.meta.hot.prune()
绑定一个清理回调。在所有导入这个模块的引用被移除之后调用,但该模块之前已经加载过。 这可以用来清理模块加载时创建的资源。相比于import.meta.hot.dispose(),这个方法更适合与 accept 和 data 配合管理有状态资源。以下是一个管理 WebSocket 的完整示例:
若使用
dispose,WebSocket 会在每次热更新时关闭并重新打开。两种写法都能避免导入文件更新时页面刷新。import.meta.hot.on() 和 off()
on() 和 off() 用于监听 HMR 运行时事件。事件名称带有前缀,避免插件间冲突。
内置事件
| 事件 | 触发时机 |
|---|---|
bun:beforeUpdate | 在热更新应用之前 |
bun:afterUpdate | 在热更新应用之后 |
bun:beforeFullReload | 在页面完全刷新前 |
bun:beforePrune | 在调用 prune 回调前 |
bun:invalidate | 当调用 import.meta.hot.invalidate() 使模块失效时 |
bun:error | 当构建或运行时发生错误 |
bun:ws:disconnect | HMR WebSocket 连接断开时,表示开发服务器可能离线 |
bun:ws:connect | HMR WebSocket 连接或重新连接时 |
为兼容 Vite,以上事件也可用带
vite:* 前缀替代 bun:*。