webpack之HMR(Hot Module Replacement)

HMR

什么是HMR?

Hot Module Replacement(HMR),当你对代码进行修改并保存后,webpack将对代码重新打包,并将模块发送到浏览器端,浏览器通过新的模块替代老的模块,
这样在不刷新浏览器的前提下就能够对应用进行更新。HMR-模块热替换功能会在应用程序运行过程中替换、添加或删除模块,而无需重新加载整个页面。

HMR是如何工作的?

  1. 修改了一个或多个文件
  2. 文件系统接受更改并通知webpack
  3. webpack重新编译构建一个或多个模块,并通知HMR服务器进行了更新
  4. HMR Server使用websockets通知HMR Runtime需要更新(HMR运行时通过HTTP请求这些更新)
  5. HMR运行时在替换更新中的模块。如果确定这些模块无法更新,则触发整个页面刷新

HMR工作流程图解

上图是webpack配合webpack-dev-server进行应用开发的模块热更新流程图

  • 上图底部红色框内是webpack代码控制的区域。蓝色方框是webpack-dev-server代码控制的区域,洋红色的方框是文件系统,文件修改后的变化就发生
    在这,而青色的方框是应用本身,步骤分析
  • 第一步,在webpack的watch模式下,webpack系统中摸一个文件发生修改,webpack监听到文件变化,根据配置文件对模块重新编译打包,并将打包后的代码通过简单的
    JavaScript对象保存自内存中
  • 第二步是wbepack-dev-server和webpack之间的接口交互,而在这一步,主要是dev-server的中间件webpack-dev-middleware和webpack之间的交互,webpack-dev-middleware调用webpack暴露的API对代码
    变化进行监控,并告诉webpack,将代码打包到内存中
  • 第三步是webpack-dev-server对文件变化的一个监控,这一步不同于第一步,并不是监控代码变化重新打包。当我们在配置文件中配置了devServer.watchContentBase为true的时候Server会监听这些配置文件中静态文件的变化,变化后
    会通知浏览器端对应用进行live reload。注意,这儿是浏览器刷新,和HMR是两个概念。
  • 第四步也是webpack-dev-server代码的工作,该步骤主要是通过sockjs(webpack-dev-server的依赖)在浏览器端和服务端之间建立一个websocket长链接,将webpack编译打包的各个阶段的状态信息告知浏览器端,
    同时也包括第三步中Server监听静态文件变化系信息。浏览器端根据这些socket消息进行不同的操作,当然服务端传递的最主要信息还是新模块的hash值。后面的步骤根据这一hash值来进行模块热替换
  • webpack-dev-server/client端并不能够请求更新的代码,也不会执行热更模块操作,而把这些工作又交给了webpack,webpack/hot/dev-server的工作就是根据webpack-dev-server/client传给他的信息
    以及dev-server的配置剧的定式刷新浏览器呢还是进行模块热更新。当然如果仅仅是刷新浏览器,也就没有后面那些步骤了、
  • HotModuleReplacement.runtime是客户端HMR的中枢,它接收到上一步传递给他的新模块的hash值,它通过JsonpMainTemplate.runtime向
    server端发送Ajax请求,服务端返回一个json,该json包含了所有要更新的模块的hash值,获取到更新列表后,该模块再次通过jsonp请求,获取到最新的模块代码。这就是7/8/9步骤
  • 而弟10步是决定HMR成功与否的关键步骤,在该步骤中,HotModulePlugin将会对新旧模块进行对比,决定是否更新模块,在决定更新模块后,检查模块之间的依赖关系,更新模块
    的同事更新模块间的以来引用
  • 最后一步,当HMMR失败后,回退到live reload操作,也就是惊醒浏览器刷新来获取最新打包代码

HMR和livereload区别?
livereload是一个web开发辅助工具,当我们修改完html、css和js的时候会自动刷新浏览器,不需要在F5了。那么liveReload和HMR有什么区别呢,liveReload是实时刷新整个页面,而HMR是更新已更改的模块,而无需重新加载页面

NamedModulesPlugin

new webpack.NameModulesPlugin(),

当开启HMR的时候使用该插件会显示模块的相对路径,建议用于开发环境

HotModuleReplacementPlugin

该插件的作用就是实现模块热替换,实际上当启动时带上--hot参数,会注入改插件

new webpack.HotModuleReplacementPlugin()

运行HMR的简单例子

  • 文件目录如下

  • hello.js内容如下
const hello = () => "hello world";
//const hello = () => "hello eleme";
export default{
    hello
}
  • index.js内容如下
import hello from "./hello.js";
import "./style.css"
function component(){
    var element = document.createElement("div");
    element.innerHTML = hello.hello();
    return element
}
console.log(hello.hello())
document.body.appendChild(component());
console.log(module)
if(module.hot){
    module.hot.accept("./hello.js",function(){
        console.log("accepting the updated printMe module",hello.hello());
    })
}

  • style.css内容如下
body{
    /*background-color: blue;*/
    background-color: black;
    color: #fff;
}
  • webpack.hmr.js
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const {CleanWebpackPlugin} = require("clean-webpack-plugin")
module.exports = {
    entry:path.resolve(__dirname,"src/index.js"),
    output:{
        filename:"bundle.js",
        path:path.resolve(__dirname,"dist")
    },
    module:{
        rules:[
            {
                test:/\.css$/,
                use:['style-loader','css-loader']
            }
        ]
    },
    plugins:[
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            title:"HMR"
        }),
        new webpack.NamedModulesPlugin(),
        new webpack.HotModuleReplacementPlugin()
    ],
    devtool:"inline-source-map",
    devServer:{
        contentBase:"./dist",
        hot:true,
        inline:true
    }
}
  • package.json
{
  "name": "webpackDevServer",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server --config demo/webpack-dev-server/webpack-dev-server.js",
    "server": "node demo/webpack-dev-middleware/server.js",
    "hmr": "webpack-dev-server  --config demo/HMR/webpack.hmr.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "clean-webpack-plugin": "3.0.0",
    "css-loader": "3.2.0",
    "express": "4.17.1",
    "html-webpack-plugin": "3.2.0",
    "style-loader": "1.0.0",
    "webpack": "4.41.2",
    "webpack-cli": "3.3.9",
    "webpack-dev-middleware": "3.7.2",
    "webpack-dev-server": "3.8.2"
  }
}
  • 执行npm run hmr

结果如下

会看到,在改变hello.js内容的时候,不用刷新,页面也自动更改,修改style.css内容,页面背景颜色也跟着在改变

猜你喜欢

转载自www.cnblogs.com/dehenliu/p/12523218.html