Webpack--模块热替换(HMR)
一、概述
(1)live reload
只要检测到代码改动就会自动重新构建,然后触发网页刷新
(2)webapack中的模块热替换
可以让代码在页面不刷新的前提下得到最新的改动,甚至不需要重新发起请求就能看到更新后的效果。
二、开启HMR
(1)HMR是需要手动开启的,并且有一些必要条件。
(2)确保项目是基于webpack-dev-server或webpack-dev-middle进行开发的,webpack本身的命令行并不支持HMR。
const webpack = require('webpack');
module.exports = {//...plugins: [new webpack.HotModuleReplacementPlugin()],devServer: {hot: true}
}
1、配置产生的结果是Webpack会为每个模块绑定一个module.hot对象,这个对象包含了HMR的API。借助这些API不仅可以实现对特定模块开启或者关系HMR,也可以添加热替换之外的逻辑。
2、调用HMR API 有两种方式,一种是手动地添加这部分代码;另一种是借助一些现成地工具,如react-hot-loader、vue-loader等。
3、如果应用的逻辑比较简单,可以直接手动添加代码来开启HMR。
//index.js
import { add } from 'util.js';
add(2, 3);
if (module.hot) {module.hot.accept();
}
假设index.js是应用的入口,可以把调用HMR API的代码放在入口中,这样HMR对于index.js和其依赖的所有模块都会生效。当发现有模块发生变动时,HMR会使应用在当前浏览器环境下重新执行一遍index.js(包括其依赖)的内容,但页面本身不会刷新。
三、HMR大致原理
(1)在本地开发环境下,浏览器是客户端,webpack-dev-server(WDS)相当于服务端。
(2)HMR的核心是客户端从服务端拉取更新后的资源(准确得说,HMR拉取的不是整个资源文件,而是chunk diff即chunk需要更新的部分)
1、WDS对本地源文件进行监听,当本地资源发生变化时WDS通过websocket向浏览器推送更新事件,并带上这次构建的hash,让客户端与上一次资源进行比对。
2、客户端发现有差别,会向WDS发送一个请求来获取更改文件的列表,即哪些模块有了改动。通常这个请求的名字为[hash].hot-update.json。
3、请求返回结果会告诉客户端,需要更新的chunk名字和hash。客户端借助这些信息继续向WDS获取该chunk的增量更新。
4、客户端处理增量更新。
四、HMR API
moudle.hot.decline:将当前文件的HMR关掉,当前文件发生改变时禁止使用HMR进行更新,只能刷新整个页面。
module.hot.accept(['./util.js']):当util.js发生改变时仍然可以启用HMR更新
五、热更新原理
(1)配置热更新
(2)npm run dev 进入 webpack-dev-server.js文件
1、webpack(config)生成一个compiler
2、new Server(compiler, options, log)生成一个server,启动一个本地服务
3、启动websocket服务,通过websocket,可以建立本地服务和浏览器的双向通信。
(3)进入webpack-dev-server/lib/Server.js
updateCompiler(this.compiler, this.options);
this.setupHooks();
this.setupDevMiddleware();
1、server里先调用updateCompiler
1)两段关键代码:一个是获取websocket客户端代码路径,另一个是根据配置获取webpack热更新代码路径。
2)作用:修改webpack.config.js的entry配置,将webpack-dev-server/client(socket)和webpack/hot/dev-server(检查更新逻辑)注入客户端。
// 修改后的entry入口
{ entry:{ index: [// 上面获取的clientEntry'xxx/node_modules/webpack-dev-server/client/index.js?http://localhost:8080',// 上面获取的hotEntry'xxx/node_modules/webpack/hot/dev-server.js',// 开发配置的入口'./src/index.js'],},
}
b、setupHooks方法
1)用来注册监听事件的,监听每次webpack编译完成。(监听了compiler.done)
2)当监听到一次webpack编译结束,就会调用_sendStats方法通过websocket给浏览器发送通知,ok和hash事件,这样浏览器就可以拿到最新的hash值了,做检查更新逻辑
c、setupDevMiddleware
1)webpack监听文件变化
2)这个方法主要执行了webpack-dev-middleware库,作用是本地文件的编译和输出以及监听,webpack-dev-server只负责启动服务和前置准备工作,所有文件相关的操作都抽离到webpack-dev-middleware库了(调用了compiler.watch方法)
3)webpack-dev-middleware最后执行setFs方法,这个方法主要目的就是将编译后的文件打包到内存。
(4)浏览器接收到热更新的通知
1)/webpack-dev-server/client/index.js,注入到客户端的代码,即websocket,接收到ok和hash事件推送。hash事件:更新最新一次打包后的hash值。 ok事件:进行热更新检查
2)ok回调函数调用reloadApp,方法又利用node.js的EventEmitter,发出webpackHotUpdate消息
3)'xxx/node_modules/webpack/hot/dev-server.js',注入到客户端的另外一个入口代码,会监听webpackHotUpdate这个事件并且获取到最新的hash,事件内部调用check。
4)check方法内部,检查更新调用的是module.hot.check方法,此方法是通过HotModuleReplacementPlugin注入的
5)module.hot.check方法内部,利用上一次保存的hash值,调用hotDownloadManifest发送xxx/hash.hot-update.json的ajax请求,请求结果获取热更新模块,以及下次热更新的Hash 标识,并进入热更新准备阶段
6)调用hotDownloadUpdateChunk发送xxx/hash.hot-update.js 请求,通过JSONP方式(JSONP获取的代码可以直接执行)
7)通过xx/hash.hot-update.js 请求获取回来的新编译后的代码是在一个webpackHotUpdate函数体内部的。也就是要立即执行webpackHotUpdate这个方法。
8) webpackHotUpdate方法内部调用hotAddUpdateChunk方法,此方法会把更新的模块moreModules赋值给全局全量hotUpdate,再调用hotUpdateDownloaded方法,hotUpdateDownloaded方法会调用hotApply进行代码的替换。
9)hotUpdate代码做的事
a、删除过期的模块,就是需要替换的模块
b、将新的模块添加到 modules 中
c、通过__webpack_require__执行相关模块的代码
(5)过程图
Webpack--模块热替换(HMR)相关推荐
- webpack 3 零基础入门教程 #12 - 如何使用模块热替换 HMR 来处理 CSS
模块热替换 是什么意思? 以前我们使用的 webpack --watch 或 webpack-dev-server 的功能是监听文件改变,就自动刷新浏览器,而这个 模块热替换 不用刷新浏览器,它是只让 ...
- webpack实践之路(七):模块热替换HMR
HMR 模块热替换(Hot Module Replacement 或 HMR)允许在运行时更新各种模块,而无需进行完全刷新. HMR主要是通过以下几种方式,来显著加快开发速度: 保留在完全重新加载页面 ...
- webpack5 基础配置8 devServer 模块热替换HMR, 框架的HRM, HRM原理
dev Server 之前运行一直是手动打开页面,修改代码后,每次都要run build非常麻烦. 第一种是通过watch来解决,每次代码一修改就自动编译然后重新渲染. 可以看到刚我们修改了代码,重新 ...
- webpack学习之2.自动编译、实时重载LiveReload、热替换HMR
代码沿用webpack学习之1.基础配置 每次要编译代码时,手动运行 npm run build 就会变得很麻烦. webpack 中有几个不同的方式,可以在代码发生变化后自动编译代码: webpac ...
- react 动态修改路由_升级到 React Router 4 并实现动态加载和模块热替换
这篇文章是升级到Webpack2坑--模块热替换失效页面不自动刷新?的后续.那篇文章主要说明了,升级到 Webpack 2 之后,通过升级webpack-dev-server和react-hot-lo ...
- webpack学习(七):启用 HMR(模块热替换)
demo地址: https://github.com/Lkkkkkkg/webpack-demo 上次使用 webpack-dev-serve : https://blog.csdn.net/qq59 ...
- 【webpack】-- 模块热替换
全称是Hot Module ReplaceMent(HMR),理解成热模块替换或者模块热替换都可以吧,和.net中的热插拔一个意思,就是在运行中对程序的模块进行更新.这个功能主要是用于开发过程中,对生 ...
- vue-cli3项目移动设备调试访问报错WDS:Disconnected,无法自动刷新或模块热替换
原文地址:https://blog.csdn.net/qq_42420120/article/details/82912944 因为默认情况下,cli3中devServer开启时默认使用的IP不是局域 ...
- Angular 热替换HMR 报错cannot find name module
热替换(Hot Module replacement) 该功能能够实现修改后页面不刷新也能更新 该功能使用websocket 实现,当后台的文件修改后,后台就会推送修改到前端,让前端替换修改的那一部分 ...
- webpack模块解析
模块 在模块化编程中,开发者将程序分解成离散功能块(discrete chunks of functionality),并称之为模块 每个模块具有比完整程序更小的接触面,使得校验.调试.测试轻而易举. ...
最新文章
- 苹果 2020 iPhone 展望:相机大升级,5G 首次接入
- 让BASH,VIM美美的Powerline
- 到时间就站起来!用树莓派爆改升降办公桌,懒癌有救了
- ajax中 get 和 post 的区别
- BASH命令和SHELL脚本学习
- vue-cli2.9.6 build项目无法访问资源 无法访问elementUI字体
- iOS常用于显示几小时前/几天前/几月前/几年前的代码片段
- Abp vNext发布v2.3!
- SHLVL 和 BASH_SUBSHELL 两个变量的区别
- java.lang.InstantiationException: DWR can't find a spring config. See the logs for solutions
- pandas - pd.date_range-生成时间索引
- mysql存储过程教程(1)
- 我是如何把SpringBoot项目的并发提升十倍量级的
- 正则表达式验证注册页面
- ecshop后台首页mysql_ECSHOP后台自带数据库管理
- Qt调节电脑屏幕亮度
- 鸿蒙试炼如何拿经验,热血精灵派空空夜夜的勇士试炼 百万经验轻松得
- 爬虫练习:爬取网易云音乐热歌榜全部歌曲的热门评论
- 计算机网络-应用层和传输层协议分析实验(PacketTracer)
- 3Com控股华为3Com 合资公司将面临新轮调整