- 开发工具
- 后端
【免费下载链接】webpack-dev-server
Serves a webpack app. Updates the browser on changes. Documentation https://webpack.js.org/configuration/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 Replacement(HMR)会在应用运行过程中交换、新增或移除模块,而无需整页刷新。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 module:example.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—— 完全关闭 HMR
module.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/false):examples/hmr/boolean/README.md - HMR 与 liveReload 组合测试:test/e2e/hot-and-live-reload.test.js
hot选项归一化与客户端入口分叉实现:lib/Server.jshot选项 Schema 定义:lib/options.json- 客户端 HMR 更新下发逻辑:client-src/index.js
- 开发工具
- 后端
【免费下载链接】webpack-dev-server
Serves a webpack app. Updates the browser on changes. Documentation https://webpack.js.org/configuration/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
开发工具后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考