Hot Module Replacement 热模块更新

热模块更新 也就是我们常说的 HMR

假如我们现在index.js文件代码有如下功能,生成一个新增按钮,点击按钮的时候,生成item

var btn = document.createElement('button');
btn.innerHTML = '新增'
document.body.appendChild(btn)


btn.onclick = function () {
    var div = document.createElement('div');
    div.innerHTML = 'item'
    document.body.appendChild(div)

运行npm run start后,我们可以看到页面已经出现了按钮

image.png

当我点击一次新增后,会出现一个item
Hot Module Replacement 热模块更新_第1张图片
image.png

这个时候,我们在index.js里引入一个 style.css文件(别忘了配置解析css的loader)
Hot Module Replacement 热模块更新_第2张图片
image.png

style.css文件里,我们给偶数位的div设置背景色
Hot Module Replacement 热模块更新_第3张图片
image.png

这样,我们点击新增后,会出现几个item,偶数的带背景
Hot Module Replacement 热模块更新_第4张图片
image.png

当我们修改 style.css文件的时候, webpack-dev-server会帮我们 重新打包,并 重新刷新浏览器,刷新后那我刚才点击生成的 item都没有了,那我要接着测试就需要重新点击按钮去新增item,这样会很麻烦

我们更换一下背景色,然后就可以看到,页面重新加载了localhost这个页面,很明显,这不是我们想要的效果


Hot Module Replacement 热模块更新_第5张图片
image.png
我希望的是,当我改变样式代码的时候,不要帮我重新刷新页面,只要帮我替换掉样式代码就可以了,页面之前渲染出的元素不要动。为了达到这样的效果,该怎么配置呢?
  1. 配置 devServer
    Hot Module Replacement 热模块更新_第6张图片
    image.png

2.Hot Module Replacement 是webpack自带的插件,所以我们要先引入 webpack

const webpack = require('webpack');
  1. 然后配置plugins,到这一步,webpack的HMR功能就已经开启了,当我们改变了webpack配置后,一定要重启一下命令,重启后,我们再去修改css文件,页面上就只会替换样式,而JS渲染的元素不会变化


    Hot Module Replacement 热模块更新_第7张图片
    image.png
HMR的好处
  1. 可以在我们写CSS 的时候,方便我们调试CSS样式(上边的例子)
  2. 当JS引入了不同的模块,而当我们更新某一个文件时,不希望刷新整个页面,而只是在页面上变更具体模块,其他已经渲染的模块不受影响,看下边例子

如果我把HMR关闭


Hot Module Replacement 热模块更新_第8张图片
image.png

Hot Module Replacement 热模块更新_第9张图片
image.png

然后在 index.js里 引入两个模块,一个是counter.js,一个是number.js


Hot Module Replacement 热模块更新_第10张图片
image.png

Hot Module Replacement 热模块更新_第11张图片
image.png

Hot Module Replacement 热模块更新_第12张图片
image.png

counter.js显示在页面上初始值是1,而且当我点击数字的时候,会加1 ; number.js就单单显示一个数字1000.
这个时候,HMR是关闭的,运行'npm run start',页面上显示


image.png

然后,我点击第一个数字,让它不停加1


Hot Module Replacement 热模块更新_第13张图片
image.png

接着,我去修改number.js把1000变为2000
Hot Module Replacement 热模块更新_第14张图片
image.png

我们会发现,1000的确是变2000了,但是第一个数据也变为初始值了,我们在看network里的DOC,发现是页面重新请求了 localhost:8080,也就是说,页面刷新了

然后我们开启HMR,重启命令,当我们再次重复刚才的步骤,点击第一个数字让其变化,更改number.js数字后,发现,页面的确是不刷新了,第二个数据却没有发生变化。这个时候,需要我们再多加一段代码


Hot Module Replacement 热模块更新_第15张图片
image.png

加了这段代码后,我们再去重复刚才的步骤,会发现,页面上多了一个模块


Hot Module Replacement 热模块更新_第16张图片
image.png

这是因为,当number.js发生变化的时候,我们重新执行了一遍 number()方法却没有把页面上原来已经渲染出来的number模块删除掉,所以我们继续完善
Hot Module Replacement 热模块更新_第17张图片
image.png

然后我们就实现了 我们希望达到的效果,也就是 counter.js和number.js两个模块在页面上更新,不会刷新页面,不会互相影响,提升了我们的开发效率


Hot Module Replacement 热模块更新_第18张图片
image.png
其实,我们引入CSS代码,也是需要if(module.hot){...}这样一段代码的,但是为什么我们没有写就实现了这样的功能呢?实际是因为,在css-loader里,已经帮我们写好了,也就是css-loader底层帮我们实现了这一段HMR的代码;我们平时用的vue也是有HMR的功能,但是我们也没写这样一段代码,是因为vue-loader底层也帮我们内置了这段代码,所以就不用我们手写了。
  • 如果我们引入了一些比较偏的文件类型,比如一些数据文件,而这些文件的loader里边,并没有内置HMR的效果,遇到这种文件,我们还是需要手动的去写下边这样一段代码的的

if (module.hot) {  //如果当前的项目,开启了HMR的功能
    module.hot.accept(' ', () => {
        do  something ....
    })
}
所以我们要指定,要想实现HMR功能,都得写这段代码,只不过有的loader帮我们内置了,就不用我们手写了

你可能感兴趣的:(Hot Module Replacement 热模块更新)