HotModuleReplacement(以下简称:HMR模块热替换)是Webpack提供的一个非常有用的功能,它允许在JavaScript运行时更新各种模块,而无需完全刷新。
HotModuleReplacement(orHMR)isoneofthemostusefulfeaturesofferedbywebpack.Itallowsallkindsofmodulestobeupdatedatruntimewithouttheneedforafullrefresh.--《HotModuleReplacement》
当我们修改代码并保存后,Webpack将对代码重新打包,HMR会在应用程序运行过程中替换、添加或删除模块,而无需重新加载整个页面。HMR主要通过以下几种方式,来显著加快开发速度:
保留在完全重新加载页面时丢失的应用程序状态;只更新变更内容,以节省宝贵的开发时间;调整样式更加快速-几乎相当于在浏览器调试器中更改样式。需要注意:HMR不适用于生产环境,这意味着它应当只在开发环境使用。
二、HMR使用方式在Webpack中启用HMR功能比较简单:
1.方式一:使用devServer1.1设置devServer选项只需要在webpack.config.js中添加devServer选项,并设置hot值为true,并使用HotModuleReplacementPlugin和NamedModulesPlugin(可选)两个Plugins:
//webpack.config.jsconstpath=require(path)constwebpack=require(webpack)module.exports={entry:./index.js,output:{filename:bundle.js,path:path.join(__dirname,/)},+devServer:{+hot:true,//启动模块热更新HMR+open:true,//开启自动打开浏览器页面+},plugins:[+newwebpack.NamedModulesPlugin(),+newwebpack.HotModuleReplacementPlugin()]}1.2添加scripts
然后在package.json中为scripts命令即可:
//package.json{//..."scripts":{+"start":"webpack-dev-server"},//...}2.方式二、使用命令行参数
另一种是通过添加--hot参数来实现。添加--hot参数后,devServer会告诉Webpack自动引入HotModuleReplacementPlugin,而不需要我们手动引入。另外常常也搭配--open来自动打开浏览器到页面。这里移除掉前面添加的两个Plugins:
//webpack.config.jsconstpath=require(path)constwebpack=require(webpack)module.exports={//...-plugins:[-newwebpack.NamedModulesPlugin(),-newwebpack.HotModuleReplacementPlugin()-]}
然后修改package.json文件中的scripts配置:
//package.json{//..."scripts":{-"start":"webpack-dev-server"+"start":"webpack-dev-server--hot--open"},//...}3.简单示例
基于上述配置,我们简单实现一个场景:index.js文件中导入hello.js模块,当hello.js模块发生变化时,index.js将更新模块。模块代码如下实现:
//hello.jsexportdefault()=hileo!;//index.jsimporthellofrom./hello.jsconstdiv=document.createElement(div);div.innerHTML=hello();document.body.appendChild(div);
然后在index.html中导入打包后的JS文件,并执行npmstart运行项目:
!DOCTYPEhtmlhtmllang="en"headmetacharset="UTF-8"/headbodydiv了不起的WebpackHMR学习指南/divscriptsrc="bundle.js"/script/body/html4.实现监听更新
当我们通过HotModuleReplacementPlugin插件启用了HMR,则它的接口将被暴露在全局module.hot属性下面。通常,可以先检查这个接口是否可访问,然后再开始使用它。举个例子,你可以这样accept一个更新的模块:
if(module.hot){module.hot.accept(./library.js,function(){//使用更新过的library模块执行某些操作...})}
关于module.hot更多API,可以查看官方文档《HotModuleReplacementAPI》。回到上面示例,我们测试更新模块的功能。这时我们修改index.js代码,来监听hello.js模块中的更新:
importhellofrom./hello.js;constdiv=document.createElement(div);div.innerHTML=hello();document.body.appendChild(div);+if(module.hot){+module.hot.accept(./hello.js,function(){+console.log(现在在更新hello模块了~);+div.innerHTML=hello();+})+}
然后修改hello.js文件内容,测试效果:
-exportdefault()=hileo!;+exportdefault()=hileo!helloworld;
当我们保存代码时,控制台输出"现在在更新hello模块了~",并且页面中"hileo!"也更新为"hileo!helloworld",证明我们监听到文件更新了。简单WebpackHMR使用方式就介绍到这,更多介绍,还请阅读官方文档《HotModuleReplacement》。
5.devServer常用配置和技巧5.1常用配置根据目录结构的不同,contentBase、openPage参数要配置合适的值,否则运行时应该不会立刻访问到你的首页。同时要注意你的publicPath,静态资源打包后生成的路径是一个需要思考的点,取决于你的目录结构。
devServer:{contentBase:path.join(__dirname,static),//告诉服务器从哪里提供内容(默认当前工作目录)openPage:views/index.html,//指定默认启动浏览器时打开的页面index:views/index.html,//指定首页位置watchContentBase:true,//contentBase下文件变动将reload页面(默认false)host:localhost,//默认localhost,想外部可访问用0.0.0.0port:,//默认inline:true,//可以监控js变化hot:true,//热启动open:true,//启动时自动打开浏览器(指定打开chrome,open:GoogleChrome)