前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >3-9-10 Hot Module Replacement 热模块更新

3-9-10 Hot Module Replacement 热模块更新

作者头像
love丁酥酥
发布2020-02-19 10:40:32
6510
发布2020-02-19 10:40:32
举报
文章被收录于专栏:coding for love

1. 简介

模块热替换(HMR - Hot Module Replacement)功能会在应用程序运行过程中替换、添加或删除模块,而无需重新加载整个页面。

2. HMR - CSS

关于 HMR 的使用场景,我们来看一个简单的示例。

代码语言:javascript
复制
// index.js
import './index.css';

var btn = document.createElement('button');
btn.innerText = 'add';
document.body.appendChild(btn);

btn.onclick = function() {
  var div = document.createElement('div');
  div.innerText = 'item';
  document.body.appendChild(div);
};
代码语言:javascript
复制
/*index.css*/
div:nth-of-type(odd) {
    background: yellow;
}

npm start 后,如下:

image.png

连续,点击 add 按钮后,如下:

image.png

这时候,如果我们修改 css,将背景色改为 blue,如下:

代码语言:javascript
复制
/*index.css*/
div:nth-of-type(odd) {
    background: blue;
}

image.png

再次点击 add 按钮后,如下:

image.png

可以看到,我们修改 css 文件时,由于代码变动,重新编译并刷新了网页。导致之前的 js 操作都消失了,有没有变法只展示我们变动的 css 呢?答案是可以的。如下配置:

代码语言:javascript
复制
const webpack = require('webpack');
...
    devServer: {
        contentBase: path.resolve(__dirname, 'dist'),
        open: true,
        port: 3000,
        hot: true, // 开启热更新
        hotOnly: true // 热更新失败时不刷新页面
    },
...
    plugins: [new HtmlWebpackPlugin({
        template: "./src/index.html"
    }), new webpack.HotModuleReplacementPlugin()]

重新编译,发现修改在即时生效的同时,保留了 js 操作,实现了 css 的热更新。

3. HMR - js

关于 js 模块的热更新该如何实现呢,我们来看一下。 首先去掉 hot 和 hot-only 配置。 增加一个 counter.js 文件和一个 number.js 文件,并引入:

代码语言:javascript
复制
// index.js
import Counter from './counter';
import Number from './number';

new Counter();
new Number();

new Number();

··· // counter.js export default function() { var div = document.createElement('div'); div.innerText = '1'; div.onclick = function() { div.innerText = (parseInt(div.innerText) + 1) + ''; }; document.body.appendChild(div); }; ···

代码语言:javascript
复制
// number.js
export default function Header() {
    var number = document.createElement('div');
    number.innerText = '1000';
    number.id = 'number';
    document.body.appendChild(number);
}

点击上面一个数字后:

image.png

修改,number 的文案为 2000,如下:

image.png

之前的 js 操作没有了,也就是 number 模块的修改影响到了 counter 模块。 我们试一下配置 hot 和 hot-only,重新编译,发现,此时修改 number 时,

image.png

number 没有被更新,这是因为依赖模块更新时,我们需要主动对更新做出响应。 如下:

代码语言:javascript
复制
// index.js
import Counter from './counter';
import Number from './number';

new Counter();
new Number();

if (module.hot) {
    module.hot.accept('./number', function() {
        new Number();
    });
}

此时,修改 number 后,有:

image.png

可以看到,webpack 并不会帮我们把原 number 干掉,然后在原位置更新一个新的 number,这些逻辑都要用户主动去实现。

代码语言:javascript
复制
// index.js
import Counter from './counter';
import Number from './number';

new Counter();
new Number();

if (module.hot) {
    module.hot.accept('./number', function() {
        document.body.removeChild(document.getElementById('number'));
        new Number();
    });
}

image.png

4. 小结

为何 js 实现 HMR 要用户手动实现更新逻辑,但是样式更新不需要呢?其实样式更新也是需要实现这个更新逻辑的,只不过 style-loader 实现了 HMR 接口,当它通过 HMR 接收到更新时,它会使用新的样式替换旧的样式。而 Vue 通过 vue-loader,react 通过 babel-preset 都在底层实现了该接口,用户无需关注。

参考

https://www.webpackjs.com/concepts/hot-module-replacement/ https://www.webpackjs.com/plugins/hot-module-replacement-plugin/ https://www.webpackjs.com/api/hot-module-replacement/

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 简介
  • 2. HMR - CSS
  • 3. HMR - js
  • 4. 小结
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档