HMR的配置
- 安装 webpack-dev-server
npm install webpack-dev-server -D
- 配置运行命令
"serve": "webpack-dev-server --config webpack.dev.config.js --color --progress --hot"
- 修改入口文件index.js
import React from 'react';
import ReactDom from 'react-dom';
import getRouter from './router/router';
// 增加的内容
if (module.hot) {
module.hot.accept();
}
ReactDom.render(
getRouter(), document.getElementById('app'));
}
tips: 在命令行中使用 --hot 或者配置了 devServer.hot = 'true' 时,webpack会默认开启HotModuleReplacementPlugin
const webpack = require('webpack');
// devServer: {
// hot: true
// }
plugins:[
new webpack.HotModuleReplacementPlugin()
]
到这里,进行测试,在项目中增加一个 div ,其中他的属性 contentEditable 为true ,然后在里面随便编辑一些内容,修改组件其中的内容保存,我们会发现,页面上该div内容不见了,页面刷新了。
大家知道,现在不是热刷新页面。热刷新的逻辑一般是放在module.accept.hot回调的逻辑里面,如下:
import component from "./component";
let demoComponent = component();
document.body.appendChild(demoComponent);
// HMR interface
if (module.hot) {
// Capture hot update
module.hot.accept("./component", () => {
const nextComponent = component();
// Replace old content with the hot loaded one
document.body.replaceChild(nextComponent, demoComponent);
demoComponent = nextComponent;
});
}
那对于一些框架的HMR怎么处理呢?他们的替换可能非常复杂,但是幸运的是通常我们不需要太多关注,业界以及提供了许多webpack Loader来提供热替换功能:
style-loader内置 Css 模块热更vue-loader内置 Vue 模块热更react-hot-reload内置 React 模块热更接口
站在使用的角度,我们只需要进行对应的loader配置即可。
react的hmr实现的原理可以参考这篇文章:【中文】React组件热加载原理及实现 - 简书
HMR的基本流程
服务端:webpack-dev-server
-
通过webpack创建compiler实例
-
new Server 设置webpack相关的hooks,其中compiler.hook.done中有向客户端发射 hash/ok 的websocket事件。
-
监听完webpack的hook以后,开始启动服务。并且把webpack-dev-middleware作为中间件。
const app = express()
const config = require('./webpack.config.js')
const compiler = webpack(config)
app.use(webpackDevMiddle(compiler))
webpack-dev-middleware 2个作用:一个是调用webpack的watch方法监听文件变化来编译文件,另外一个是把文件读取到内存中。
-
开启webserver和websocket服务
-
文件编译完成,调用步骤2注册的事件。从而触发hash事件,通知客户端。
客户端
-
客户端监听到hask/ok事件以后,触发webpackHotUpdate事件。
-
执行hotCheck,module.hot.check
-
拉取hash.hot-update.json来确认要更新的文件,和下次请求的hash值。通过json拉取最新的hash.hot-update.js代码。
-
利用HotModuleReplacement,runtime.js 注册到全局window的webpackHotUpdate方法,执行hotUpdate进行更新。
-
最后一步,当 HMR 失败后,回退到 live reload 操作,也就是进行浏览器刷新来获取最新打包代码。
参考: