webpack热更新HMR的使用

前言

虽然我们通过webpack-dev-server可以实现修改代码后的自动刷新,但还是有一些不如人意的地方。例如我们在页面中输入一段内容,希望对这段进行样式修改,然而我们修改样式后webpack-dev-server自动刷新了,我们之前输入的内容也被刷新清除掉了,而HMR就是用来解决这样的问题的。

一、HMR初体验

HMR ==》 Hot Module Replacement

HMR是配合webpack-dev-server来使用的,所以别忘了安装webpack-dev-server。

启用HMR也很简单,在webpack.config.js中配置devserver中的hot属性和添加一个webpack内置的HotModuleReplacementPlugin插件。

const webpack = require("webpack")

module.exports = {
	...,
	devServer:{
      hot: true
    },
    plugins:[
    	new webpack.HotModuleReplacementPlugin()
    ]
}

启动服务器看看效果,yarn webpack serve,通过webpack5.X需要通过webpack的serve命令运行webpack-dev-server。

先试试修改css样式的效果。
在这里插入图片描述
在这里插入图片描述
css样式能够直接修改而不会改变现有状态。

再试试修改js内容:

在这里插入图片描述
添加了一段console.log()代码后,页面更新,但之前的状态也没保存下来。

这是因为webpack中的HMR需要手动处理模块热替换逻辑。而样式不需要手动处理是因为样式文件经过loader处理了,我配置了css-loader和style-loader处理css文件,在style-loader中会自动处理样式文件的热更新。

为什么样式可以自动处理,js就不行?因为样式模块更新过后,只需要把更新后的css及时替换到页面中,就可以覆盖之前的样式,从而实现样式的更新;

而我们所编写的js是没有任何规律的,我们可能导出一个对象、数组、字符串,我们对导出成员的使用也是各不相同的,所以webpack对这些毫无规律的js模块,就不知道如何去处理更新的模块,也就没有办法去帮我们实现一个可以通用所有情况的模块替换方案。

但是像使用了vue-cli/create-react-app这类脚手架的项目实现热更新不需要手动处理js模块的更新,也能实现热更新,这是因为使用的是框架,使用框架开发时,项目中的每个文件都有了规律,因为框架提供的就是一些规则,通过脚手架创建的项目内部集成了HMR方案。

总结:我们需要手动处理js模块更新后的热替换。

二、手动处理模块更新后的热替换逻辑

我们需要通过HMR的api来处理模块更新后的热替换,这些处理逻辑都写在我们的入口文件中。
因为打包从入口文件开始,也就是在这个文件开始去加载其他模块,就是因为这个文件中使用了导入的模块,一旦当这些模块更新了,就需要去重新使用这些模块,所以我们需要在这里去处理模块更新后的热替换。
在HMR的api中,为module对象提供了一个hot属性,这个属性也是一个对象,这也是HMR的核心对象,它提供了一个accept方法,用于去注册当某一个模块更新后的处理函数,这个方法第一个参数接收的是依赖模块的路径,第二个参数是依赖路径更新后的处理函数。

// 引入模块
import createEditor from "./editor.js"
const editor = createEditor()
document.body.append(editor)

// 定义lastEditor接收最后的editor组件
let lastEditor = editor
module.hot.accept('./editor.js', () => {
        // console.log('editor.js模块更新了');
        
        const val = lastEditor.innerHTML // 获取内容
        // console.log("lastEditor.innerHTML", val);
        document.body.removeChild(lastEditor) // 移除旧的组件
        const newEditor = createEditor() // 创建新组件
        newEditor.innerHTML = val // 将之前的内容放进去
        document.body.append(newEditor) // 添加到DOM中
        lastEditor = newEditor // lastEditor接收最新的组件,方便下次更新处理
    })
// editor.js 内容

import './editor.css'

export default () => {
    const editor = document.createElement("div")
    editor.className = "div"
    editor.contentEditable = true
    console.log('已经测试过了');
    return editor;
}

效果如下:
在这里插入图片描述
在这里插入图片描述
现在就能在修改editor.js里的内容并且实现热更新了,但只限于editor.js中,如果想要在其他组件的js中实现,需要单独去处理热更新逻辑。

三、HMR注意事项

  1. 处理HMR的代码报错会导致自动刷新(解决办法,使用hotOnly,就是将配置中的hot:true改成hotOnly:true)
  2. 没启用HMR的情况下,使用HMR api会报错,即如果没配置new webpack.HotModuleReplacementPlugin()和hot属性的话,使用module.hot.accept会报错(解决办法:加上一个if(module.hot)判断)
  3. 代码中多了一些与业务无关的代码(在将hot与webpack.HotModuleReplacementPlugin注释掉后,执行打包,可以发现打包入口文件中的热更新处理代码都被处理掉了。这里处理掉代码的前提是加上了第2点中的if判断)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值