先附上测试代码进行说明
html文件
<body>
<div>webpack5学习</div>
<!-- 注释 -->
<div>html压缩</div>
<div class="box1"></div>
<div class="box2"></div>
<div class="img-box1"></div>
<div class="img-box2"></div>
<div class="img-box3"></div>
<img src="./img/react.png" alt="react" />
</body>
js入口文件
import '../css/style1.css'
import '../css/style2.less'
import test from './test.js'
console.log('index.js执行了')
test()
function add(a, b) {
return a + b;
}
console.log(add(1, 3))
test.js
console.log('test.js执行了')
function test() {
const value = 'hello world 11'
console.log('value: ', value)
}
export default test;
css和style文件依然是前面文章中的样式,在这就不再重新粘贴。
不开启热更新的状况
js文件的情况
不开启热更新时,我们修改print.js中的代码时,会导致整个页面全部都重新加载。
样式文件的情况
不开启热更新时,修改css中的样式时,页面会自动刷新,并且只会刷新被修改的样式文件。
可以看到没有开始热更新时,css等样式文件也已经满足了热更新的需求。这是因为style-loader已经实现了热更新功能。我们现在就集中来说说html和js的热更新。
热更新HMR
HMR:hot module replacement 热模块更新/热模块替换
作用:一个模块发生变化,只会重新打包这一个模块,而不是打包所有模块。极大提升构建速度。
如何开启HMR热更新功能
在devServer的配置中添加hot:true
devServer: {
// 项目构建后的路径,也就是代码要运行的项目目录
static: resolve(__dirname, 'build'),
//compress是否启动gzip压缩,让代码体积更小,速度更快
compress: true,
// 指定开发服务器的端口号
port: 3000,
// open是否自动打开浏览器,打开的是默认浏览器。
open: true,
// 开启HMR功能
hot: true
}
js文件热更新
js文件的热更新需要在入口文件index.js中通过HMR监听其他文件的变化
//module.hot为true,说明开启了HMR功能。
if (module.hot) {
module.hot.accept('./test.js', function () {
// module.hot.accept这个方法会监听test.js文件的变化,一旦发生变化,其他模块不会重新打包构建,会执行后面的回调函数
// 需要将关键性的函数再重新执行一遍
test()
})
}
测试:修改test.js
可以看到修改之后,只重新加载了test.js,其他文件并没有重新加载。
注意:
HMR功能对js处理,只能处理非入口js文件的其他文件。因为入口文件会引入其他依赖,入口文件改变引起其他依赖重新加载是没办法避免的。
HTML文件
虽然开启了热更新,但是修改index.html文件中的内容,页面并不会自动更新。
html默认不能使用HMR功能。开启HMR功能之后会导致问题:html文件不能自动刷新了。
解决:在webpack.config.js的中将html也添加到入口处,重新执行npx webpack-dev-server命令。
将html添加到入口处之后,开启HMR功能之后,再修改html文件时,浏览器会自动刷新。并且会发现所有的日志重新打印了,也就是说项目重新加载了,并不是我们希望的那样只修改html文件。
解释:HMR热更新是一个模块变,只重新打包这一个文件,例如有n个js文件,其中一个js发生变化,就只重新打包这一个js文件,其他的(n-1)个文件不变。而html只有一个,并且hmtl文件也被添加到了入口处,所以一旦html发生变化,所以内容重新加载是正常的。html文件并不需要做HMR功能。