• 【webpack】HMR热更新原理


    本文:参考文章

    一、HMR是什么,为什么出现

    1、出现的原因

    之前,应用的加载、更新都是一个页面级别的操作,即使单个代码文件更新,整个页面都要刷新,才能拿到最新的代码同步到浏览器,导致会丢失之前在页面执行过程中的所有交互状态

    2、HMR作用

    可以将大多数小改动通过热模替换方式更新到页面上,保存一定的交互效果,从而确保连续的、顺畅的开发调试

    二、HMR应用

    1、Vue启动HMR

    (1)搭建vue项目环境

    • npm install vue
    • 在src文件夹下创建main.js文件
    import {createApp} from 'vue'
    import App from './App.vue'
    
    createApp(App).mount('#app')
    
    • 1
    • 2
    • 3
    • 4
    • 在src文件夹下创建component文件夹里创建Helloworld.vue文件
    <template>1</template>
    
    • 1
    • 在src文件夹下创建App.vue文件
    <template>
      <div>
        <h1>Hello Vue 3 with HMR!!</h1>
        <p>{{ count }}</p>
        <input>
        <Helloworld></Helloworld>
      </div>
    </template>
    
    <script>
    import Helloworld from './component/Helloworld.vue';
    export default {
      data() {
        return {
          count:0
        };
      },
      components:{
        Helloworld
      },
      created(){
        this.handle = setInterval(() => {
            this.count++
        }, 1000);
      }
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 根目录创建index.html文件
    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Documenttitle>
    head>
    <body>
        <div id="app">div>
    	// 引入main.js文件
        <script src="./dist/main.js" type="module">script>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    (2)下载vue-loader、@vue/compiler-sfc、html-webpack-plugin配置webpack.config.js文件
    npm i vue-loader,配置loader,并引入VueLoaderPlugin插件
    版本号:

    • vue-loader:17.2.2
    • html-webpack-plugin:5.5.3
    • @vue/compiler-sfc:3.3.4
    • webpack:5.88.2
    const path = require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    const {CleanWebpackPlugin} = require('clean-webpack-plugin')
    const {VueLoaderPlugin} = require('vue-loader')// HMR
    
    // import { Configuration } from 'webpack'
    /**
     * @type {Configuration}
     */
    const config = {
        mode:'development',
        entry:'./src/main.js',
        output:{
            path:path.resolve(__dirname,'dist'),
            filename:'[name].js'
        },
        module:{
            rules:[
                {
                    test:/\.vue?$/,
                    loader:'vue-loader',
                    options:{
    					hotReload:true // 手动可以关闭热更新
    				}
                }
            ]
        },
        plugins:[
            new HtmlWebpackPlugin({template:'./index.html'}),
            new CleanWebpackPlugin(),
            new VueLoaderPlugin()
        ],
        devtool:'source-map',
        devServer:{
            port:8080
            hot:true // 开启HMR
        }
    }
    
    module.exports = config
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    最后呈现的效果:

    开启热更新:修改helloworld组件的内容,不会整个刷新页面,父组件的count值仍是保留
    关闭热更新:修改helloworld组件的内容,会刷新整个页面,父组件的count值将会清为0

    2、一些零碎的知识点

    关于webpack当中的devServer:
    devServer在webpack5的版本用hot:true,就可以开启热更新。
    devServer启动会根据webpack.config.js配置文件去读取配置(主要是读取output.path配置),先去对文件进行打包编译,在编译之后不会将打包文件输出在dist目录下,而是存储在内存当中,保证了是挂在server的根路径一样的效果,随便去访问。
    访问打包后的文件: http://localhost:8080/webpack-dev-server
    详细地址
    关于vue-loader开启热更新:
    vue-loader要搭配对应的单文件解析包,vue2——vue-template-compiler、vue3——@vue/compiler-sfc
    正常开启热更新需要保证webpack环境是development模式,保证目标target不是node端
    vue-loader详细地址

    三、HMR的工作原理

    1、webpack-dev-server在热更新中做了什么?

    当运行的时候,它会向客户端添加两个文件,这两个文件的目的:
    1、websocket文件用于与服务端进行通信
    2、客户端获取到需要更新的模块,进行重新执行并更新。

    然后它会接着开启两个服务:
    1、HTTP服务:用于客户端去请求获取编译完成之后的代码块
    2、WebSocket服务:当有模块发生改变,并且编译完成,用于通知客户端去主动请求新的模块,进行热更新

    2、更加细节的真实操作

    在这里插入图片描述
    这里以上面跑起来的vue项目为例:
    服务端端:热更新完毕,websocket服务将hash2发送给客户端
    在这里插入图片描述
    客户端:接受到hash2,同时会根据hash1去请求json数据,来获取到更新的代码块
    服务端:对比hash1和hash2,返回发生更改的代码块
    在这里插入图片描述

    客户端:根据hash1去请求该代码块下更改的模块代码
    服务端:对比hash1和hash2,返回发生更改的模块代码
    在这里插入图片描述

    客户端:根据更新的模块代码,去更新并执行依赖该模块的代码

  • 相关阅读:
    亚马逊平台不给力?来Starday,告诉你什么是真正的高阶玩法
    算法高级部分--并查集:方块栈(POJ1988)
    双软认证需要材料,怎么办理
    【MyBatis笔记08】Mybatis中常用的一些操作
    【符号链接】【bash】遍历目录下的每个子项目
    微信小程序 自定义tab不煽动
    IDEA版SSM入门到实战(Maven+MyBatis+Spring+SpringMVC) -Maven核心概念
    十八、一起学习Lua 调试(Debug)
    【Java】工作中常用的一些lambda表达式
    【C++从0到王者】第二十八站:二叉搜索树的应用
  • 原文地址:https://blog.csdn.net/Triumph_light/article/details/132531364