webpack HMR原理

515 阅读2分钟

HMR的配置

  1. 安装 webpack-dev-server
npm install webpack-dev-server -D
  1. 配置运行命令
"serve": "webpack-dev-server --config webpack.dev.config.js --color --progress --hot"
  1. 修改入口文件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

  1. 通过webpack创建compiler实例

  2. new Server 设置webpack相关的hooks,其中compiler.hook.done中有向客户端发射     hash/ok 的websocket事件。

  3. 监听完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方法监听文件变化来编译文件,另外一个是把文件读取到内存中。

  1. 开启webserver和websocket服务

  2. 文件编译完成,调用步骤2注册的事件。从而触发hash事件,通知客户端。

    客户端

  3. 客户端监听到hask/ok事件以后,触发webpackHotUpdate事件。

  4. 执行hotCheck,module.hot.check

  5. 拉取hash.hot-update.json来确认要更新的文件,和下次请求的hash值。通过json拉取最新的hash.hot-update.js代码。

  6. 利用HotModuleReplacement,runtime.js 注册到全局window的webpackHotUpdate方法,执行hotUpdate进行更新。

  7. 最后一步,当 HMR 失败后,回退到 live reload 操作,也就是进行浏览器刷新来获取最新打包代码。

参考:

    看完这篇,面试再也不怕被问 Webpack 热更新 - 掘金

    Webpack HMR 原理解析