ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

webpack-dev-server 的 `hot: “only“` 模式:构建失败时不刷新页面的 HMR 降级方案

webpack-dev-server 的 `hot: “only“` 模式:构建失败时不刷新页面的 HMR 降级方案 开发工具后端【免费下载链接】webpack-dev-serverServes a webpack app. Updates the browser on changes. Documentation https://webpack.js.org/configuration/dev-server/.项目地址https://gitcode.com/gh_mirrors/we/webpack-dev-server点击查看免费下载导读hot: only是 webpack-dev-server 在devServer.hot配置中提供的一种特殊取值它开启热模块替换HMR但在某个模块无法被热更新接受unaccepted module时只做模块级降级绝不回退到整页刷新。本文将基于 examples/hmr/only/README.md 的示例结合 lib/Server.js、lib/options.json 与 client-src/index.js 的源码实现讲清hot: only的配置方法、行为差异、底层原理以及适用场景。读完你既能直接运行官方示例复现效果也能理解它和hot: true在编译入口与降级策略上的本质区别。一、hot: only是什么Hot Module ReplacementHMR会在应用运行过程中交换、新增或移除模块而无需整页刷新。webpack-dev-server 通过devServer.hot选项控制该功能的开关它接受两种取值形态取值含义true启用 HMR并允许在 HMR 失效时回退为整页刷新only启用 HMR但在构建失败或模块无法热更新时不回退整页刷新false完全禁用 HMR在 lib/options.json 的 JSON Schema 中Hot定义正是这样声明的Hot: { anyOf: [ { type: boolean, cli: { negatedDescription: Disables Hot Module Replacement. } }, { enum: [only] } ], description: Enables Hot Module Replacement., link: https://webpack.js.org/configuration/dev-server/#devserverhot }也就是说only是唯一被允许的字符串枚举值其余任何非布尔值都会在配置归一化阶段被处理详见下文第三节。这保证了配置在 schema 校验层就杜绝了拼写错误。二、配置与启动方式1. 在 webpack 配置文件中启用参考示例 examples/hmr/only/webpack.config.js最简配置如下module.exports { // ... devServer: { hot: only, }, };示例中完整配置为import { setup } from ../../util.js; export default setup( { context: import.meta.dirname, entry: ./app.js, devServer: { hot: only, }, }, import.meta.url, );这里setup是 examples/util.js 提供的辅助函数负责为示例补充 dev-server 运行时所需的后台配置位entry指向app.js由它导入example.js。2. 通过 CLI 启动也可以在命令行直接指定效果与配置文件等价npx webpack serve --open --hot only其中--open会在默认浏览器中打开页面--hot only等价于devServer.hot: only。三、源码视角only是如何被处理与生效的1. 配置归一化非布尔、非only一律回退为true在 lib/Server.js 的选项归一化逻辑中options.hot typeof options.hot boolean || options.hot only ? options.hot : true;即只有boolean或字符串only会被原样保留其余任何取值包括未设置最终都会归一化为true。这解释了为什么hot: only能够稳定通过校验并被后续逻辑识别。2. 客户端入口选择only-dev-server与dev-server的分叉hot: only与hot: true最关键的实现差异体现在客户端热更新入口的选择上。在 lib/Server.js 的getClientHotEntry()中getClientHotEntry() { if (this.options.hot only) { return cjsRequire.resolve(webpack/hot/only-dev-server); } else if (this.options.hot) { return cjsRequire.resolve(webpack/hot/dev-server); } }hot: true注入的是webpack/hot/dev-server当某个模块无法被accept时它会通过location.reload()触发整页刷新作为兜底hot: only注入的是webpack/hot/only-dev-server它不注册刷新兜底更新失败时仅记录日志页面保持原状。这正是文档中Enables Hot Module Replacement without page refresh as a fallback in case of build failures这句描述的源码依据。3. WebSocket 握手阶段下发hot消息当客户端 socket 连接建立后服务端会根据 hot 选项推送能力消息。在 lib/Server.js 中if (this.options.hot true || this.options.hot only) { this.sendMessage([client], hot); }即无论hot是true还是only客户端都会被通知开启 HMR 能力区别只在于后续遇到不可接受模块时客户端的降级行为。客户端侧在 client-src/index.js 的reloadApp中会通过webpackHotUpdate事件驱动 HMR 运行时执行热替换并输出[webpack-dev-server] App hot update...日志。四、动手复现官方示例的运行步骤与预期输出1. 示例文件构成examples/hmr/only/app.js入口模块通过import.meta.webpackHot.accept()注册 HMR 接受回调import ./example.js; if (import.meta.webpackHot) { import.meta.webpackHot.accept((err) { if (err) { console.error(Cannot apply HMR update., err); } }); }examples/hmr/only/example.js负责渲染页面文本的模块const target document.querySelector(#target); target.innerHTML Modify and save code/examples/hmr/example.js/code to update this element without reloading the page.;2. 操作步骤按第二节的方式启动 dev-server脚本应在默认浏览器中打开http://localhost:8080/在编辑器中打开example.js修改innerHTML字符串的任意部分并保存打开浏览器开发者工具的控制台Console。3. 预期控制台输出在hot: only模式下由于app.js声明了 HMR 接受逻辑而example.js本身没有被显式accept更新会产生如下输出[webpack-dev-server] App updated. Recompiling... [webpack-dev-server] App hot update... [HMR] Checking for updates on the server... ⚠️ Ignored an update to unaccepted module ./example.js - ./app.js [HMR] Nothing hot Updated. [HMR] App is up to date.关键信息解读Ignored an update to unaccepted moduleexample.js不是被接受accepted的模块HMR 运行时选择忽略该更新Nothing hot Updated.本轮没有模块被实际热替换全程没有任何location.reload/ 页面刷新动作——这就是only模式与true模式的本质差别。4. 验证降级行为完成上述步骤后手动刷新页面可以看到页面上的文本确实变成了你在example.js中的修改。这说明在hot: only模式下未接受模块的变更不会自动生效必须依赖手动刷新这正是构建失败时不自动回退刷新这一语义的直观体现。五、与hot: true/hot: false的行为对照同一目录下的 examples/hmr/boolean/README.md 提供了另两种模式的对照示例可结合理解三者的差异1.hot: true—— 允许整页刷新兜底module.exports { // ... devServer: { hot: true, }, };CLI 等价写法npx webpack serve --open --hot同样修改example.js的innerHTML控制台输出为[webpack-dev-server] App updated. Recompiling... [webpack-dev-server] App hot update... [HMR] Checking for updates on the server... [HMR] Updated modules: [HMR] - ./example.js [HMR] App is up to date.且页面文本会自动变化。因为hot: true注入的是webpack/hot/dev-server当模块可被接受时完成热替换当遇到无法接受的构建失败场景时它会退化为整页刷新保证页面内容始终与最新代码一致——代价是可能丢失当前页面状态。2.hot: false—— 完全关闭 HMRmodule.exports { // ... devServer: { hot: false, }, };CLI 等价写法npx webpack serve --open --no-hot此时修改example.js后页面文本不会自动变化也不会触发整页刷新除非额外开启liveReload一切变更都需要手动刷新页面才能看到。3. 三者对比小结模式是否注入 HMR 运行时模块可接受时构建失败 / 模块不可接受时hot: true是dev-server热替换页面自动更新自动整页刷新兜底hot: only是only-dev-server热替换页面自动更新只记录日志不回退刷新hot: false否无 HMR无 HMR变更需手动刷新六、适用场景与实战建议状态敏感的调试场景正在调试表单输入、滚动位置、动画等页面状态时hot: only可避免构建失败导致整页刷新、状态全部丢失的体验断裂代价是失败后需要手动刷新。与import.meta.webpackHot.accept()配合使用示例中app.js通过accept声明接受更新这是让热替换真正生效的前提。若模块树中某一环未接受更新only模式会直接忽略该更新而非刷新页面。团队规范约束如果希望强制团队成员要么优雅热替换、要么显式手动刷新hot: only比hot: true更能暴露未正确处理 HMR 的模块——控制台中持续的Ignored an update to unaccepted module警告就是定位热更新失效模块的线索。注意与liveReload的叠加效果hot控制的是 HMR 层面的刷新行为而liveReload默认true是另一个独立的整页刷新通道。需要完全不做整页刷新的纯粹 HMR 体验时还应显式评估liveReload的设置避免两者叠加后产生意外刷新。七、进一步阅读HMR 完整行为示例true/falseexamples/hmr/boolean/README.mdHMR 与 liveReload 组合测试test/e2e/hot-and-live-reload.test.jshot选项归一化与客户端入口分叉实现lib/Server.jshot选项 Schema 定义lib/options.json客户端 HMR 更新下发逻辑client-src/index.js赞分享开发工具后端【免费下载链接】webpack-dev-serverServes a webpack app. Updates the browser on changes. Documentation https://webpack.js.org/configuration/dev-server/.项目地址https://gitcode.com/gh_mirrors/we/webpack-dev-server点击查看免费下载相关推荐webpack-dev-server 的 hot 配置详解HMR 热更新true / false / only实战指南webpack dev server 的 hot 配置详解HMR 热更新true / false / only实战指南 导读 hot 是 webpac开发工具后端告别页面刷新Webpack模块热更新(HMR)的黑科技实现告别页面刷新Webpack模块热更新 HMR 的黑科技实现 Webpack作为JavaScript应用的打包工具其模块热更新Hot Module Repl前端构建开发工具TVM TIRx Tile Primitive Dispatch 全解TilePrimitiveCall 的选型、下降与扩展机制TVM TIRx Tile Primitive Dispatch 全解TilePrimitiveCall 的选型、下降与扩展机制 导读TIRx 是 TVM开发工具后端上一篇5分钟上手Linux桌面自动化神器AutoKey从入门到效率翻倍下一篇为什么空闲AI Agent如此昂贵Agent Substrate用30倍超配给出完整答案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进