HMR 为什么能保留状态?什么时候仍然需要整页刷新?
先理解原理和示例,再练习完整口述与追问。
回答要点
模块图定位更新;accept 边界接纳变更;dispose 清理旧副作用;框架决定组件状态是否保留;不保证所有修改都热替换。
原理拆解
HMR 是开发期在不完整刷新页面的情况下替换、增加或移除模块的机制。开发服务器检测文件变化后生成更新信息,浏览器中的运行时代码获取变更,并沿依赖图寻找能接受更新的边界。模块或框架适配层可以声明 accept 接纳依赖更新,并通过 dispose 清理旧实例的副作用、传递必要数据。
页面没有整个重载,所以其他未受影响部分的状态有机会保留;Vue、React 等工具进一步根据组件类型和编辑内容决定能否复用组件状态。修改导出形态、组件签名、全局初始化逻辑,或找不到可接纳边界时,可能回退为整页刷新,因此不能保证所有修改都保留表单输入。
最常见的问题是热更新时重复注册事件、定时器和全局订阅,应在 dispose 或组件生命周期中清理。CSS 热更新、组件热更新和服务端进程重启也是不同层面的能力。HMR 服务应按开发环境使用,生产发布仍依赖正式构建、缓存与版本策略,而不是把热更新通道开放出去当部署方式。
参考:Webpack HMR。
示例与推演
模块 A 依赖 B,B 改变后先寻找能接纳更新的边界;若 A 接纳 B,则应用新实现,否则可能继续向上传播并回退刷新。B 曾注册 window 监听,应在 dispose 清理旧 handler,否则每次热更新都会叠加一份监听。
易错点
保留页面不等于保留所有组件状态。服务端模块变更需要的进程重启,与浏览器 HMR 是不同层面的能力。
参考回答可直接练习口述
HMR 是开发期在不完整刷新页面的情况下替换、增加或移除模块的机制。开发服务器检测文件变化后生成更新信息,浏览器中的运行时代码获取变更,并沿依赖图寻找能接受更新的边界。模块或框架适配层可以声明 accept 接纳依赖更新,并通过 dispose 清理旧实例的副作用、传递必要数据。