zoukankan      html  css  js  c++  java
  • 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内容,页面背景颜色也跟着在改变

  • 相关阅读:
    jstl插件使用
    IDEA配置tomcat
    Spring框架
    2020/7/17 JAVA模拟斗地主发牌洗牌
    2020/7/15 JAVA之Map接口
    2020/7/14 Java之增强for循环、泛型、List接口、Set接口
    2020/7/13 集合之ArrayList集合、Collection接口、Iterator迭代器
    2020/7/13 常用API之基本类型包装类、System类、Math类、Arrays类、大数据运算
    2020/7/11 日期相关类
    2020/7/8 JAVA总结之:匿名对象/内部类/包的声明与访问/访问修饰符/代码块
  • 原文地址:https://www.cnblogs.com/dehenliu/p/12523218.html
Copyright © 2011-2022 走看看