Webpack
中文文档:
模块热替换 | webpack 中文文档
:::info
webpack-dev-server
隐藏的特性:webpack-dev-server
依然帮我们打包成一个dist
目录只不过存在于电脑的内存当中,这样有效的提升了打包的速度。
:::
什么是HMR
(hot-module-replacement
)热模块替换?**HMR**
就是在更改代码的时候页面内容发生变化但是不进行页面刷新。
CSS 热更新
import "./style.css";
var btn = document.createElement("button");
btn.innerHTML = "新增";
btn.addEventListener("click", function () {
var div = document.createElement("div");
div.innerHTML = "item";
document.body.appendChild(div);
})
document.body.appendChild(btn);
div:nth-of-type(odd) {
background-color: antiquewhite;
}
以上代码实现了当我点击页面的button
按钮的时候就往页面进行一个div
,div
的背景色为antiquewhite
,但是加入我把div
样式文件替换成pink
后,页面就进行了刷新,我们新增的item
也被丢失了,而热模块替换就是解决这个问题的。
div:nth-of-type(odd) {
background-color: pink;
}
配置
方法一:直接配置devServer
module.exports = {
// ...
devServer: {
contentBase: "./dist",
open: true,
hot: true, // 让 webpack-dev-server 开启 HMR 的功能
hotOnly: true, // 即便 css 样式没有生效也不让浏览器自动刷新页面
},
}
方法二:实例化webpack.HotModuleReplacementPlugin()
构造函数
const webpack = require("webpack");
module.exports = {
// ...
devServer: {
contentBase: "./dist",
open: true,
hot: true, // 让 webpack-dev-server 开启 HMR 的功能
hotOnly: true, // 即便css样式没有生效也不让浏览器自动刷新页面
},
// ...
plugins: [
new webpack.HotModuleReplacementPlugin();
]
}
然后我们进行样式修改后就会发现页面的样式进行了改变,页面也没有刷新,我新增的item
也没有丢失,仅仅是item
的背景颜色发生了改变,这样就极大了提示我们的开发效率。
div:nth-of-type(odd) {
background-color: aquamarine;
}
JS 热更新
同样的效果也适用于JS
文件:
// import "./style.css";
// var btn = document.createElement("button");
// btn.innerHTML = "新增";
// document.body.appendChild(btn);
// btn.addEventListener("click", function () {
// var div = document.createElement("div");
// div.innerHTML = "item";
// document.body.appendChild(div);
// })
import counter from './counter';
import number from './number';
counter();
number();
export default function () {
let div = document.createElement("div");
div.setAttribute("id", "counter");
div.innerHTML = "1";
div.onclick = function () {
div.innerHTML = parseInt(div.innerHTML, 10) + 1
}
document.body.appendChild(div);
}
export default function () {
let div = document.createElement("div");
div.setAttribute("id", "number");
div.innerHTML = "1000";
document.body.appendChild(div);
}
以上代码我们能实现在页面上显示 1 和 1000,假设现在点击 1 就会自加 1 到10,接着去修改number.js
中的 1000 为 2000 的时候,页面没有进行刷新,依然是 10 和 1000(如果没有开启热更新,当修改为 2000 的时候,页面就会刷新为 1 和 1000)。
如果解决这个问题呢?
import number from './number';
import counter from './counter';
counter();
number();
// 如果当前项目开启了热更新
if (module.hot) {
// 执行回调函数
module.hot.accept("./number.js", () => {
// 移除之前的 number,重新执行一下 number()
document.body.removeChild(document.getElementById("number"));
number();
})
}
现在点击 1 自加到任何数值,去代码里修改number.js
中的 数字,页面就只会更新number.js
,不会影响counter
元素。
:::warning
为什么js
文件需要手动执行呢,而css
文件就不需要呢?
这是因为css-loader
已经帮我们做了这个操作,还有vue-loader
也在内部帮我们做了这个操作。
:::