本篇内容主要讲解“怎么理解Webpack HMR”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解Webpack HMR”吧!一、HMR 介绍Hot Module Replacement(以下简称:HMR 模块热替换)是 Webpack 提供的一个非常有用的功能,它允许在 JavaScript 运行时更新各种模块,而无需完全刷新。Hot Module Replacement (or HMR) is one of the most useful features offered by webpack. It allows all kinds of modules to be updated at runtime without the need for a full refresh. –《Hot Module Replacement》当我们修改代码并保存后,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 命令即可:2. 方式二、使用命令行参数另一种是通过添加 –hot 参数来实现。添加 –hot 参数后,devServer 会告诉 Webpack 自动引入 HotModuleReplacementPlugin ,而不需要我们手动引入。另外常常也搭配 –open 来自动打开浏览器到页面。这里移除掉前面添加的两个 Plugins :然后修改 package.json 文件中的 scripts 配置:3. 简单示例基于上述配置,我们简单实现一个场景:index.js 文件中导入 hello.js 模块,当 hello.js 模块发生变化时, index.js 将更新模块。模块代码如下实现:然后在 index.html 中导入打包后的 JS 文件,并执行 npm start 运行项目:4. 实现监听更新当我们通过 HotModuleReplacementPlugin 插件启用了 HMR,则它的接口将被暴露在全局 module.hot 属性下面。通常,可以先检查这个接口是否可访问,然后再开始使用它。举个例子,你可以这样 accept 一个更新的模块:关于 module.hot 更多 API ,可以查看官方文档《Hot Module Replacement API》 。回到上面示例,我们测试更新模块的功能。这时我们修改 index.js 代码,来监听 hello.js 模块中的更新:然后修改 hello.js 文件内容,测试效果:当我们保存代码时,控制台输出 “现在在更新 hello模块了~” ,并且页面中 “hi leo!” 也更新为 “hi leo! hello world” ,证明我们监听到文件更新了。简单 Webpack HMR 使用方式就介绍到这,更多介绍,还请阅读官方文档《Hot Module Replacement》。5. devServer 常用配置和技巧5.1 常用配置根据目录结构的不同,contentBase、openPage 参数要配置合适的值,否则运行时应该不会立刻访问到你的首页。同时要注意你的 publicPath,静态资源打包后生成的路径是一个需要思考的点,取决于你的目录结构。5.2 技巧1:文件形式输出 dev-server 代码dev-server 输出的代码通常在内存中,但也可以写入硬盘,产出实体文件:通常可以用于代理映射文件调试,编译时会产出许多带 hash 的 js 文件,不带 hash 的文件同样也是实时编译的。5.3 技巧2:默认使用本地 IP 启动服务有的时候,启动服务时,想要默认使用本地的 ip 地址打开:同时还需要将 host 配置为 0.0.0.0,这个配置建议在 scripts 命令中追加,而非在配置中写死,否则将来不想要这种方式往回改折腾,取巧一点,配个新命令:5.4 技巧3:指定启动的调试域名有时启动的时候希望是指定的调试域名,例如:local.test.baidu.com:同时需要将 127.0.0.1 修改为指定的 host,可以借助 iHost 等工具去修改,各个工具大同小异,格式如下:服务启动后将自动打开 local.test.baidu.com:8080 访问5.5 技巧4:启动 gzip 压缩三、HMR 基本原理介绍从前面介绍中,我们知道:HMR 主要功能是会在应用程序运行过程中替换、添加或删除模块,而无需重新加载整个页面。那么,Webpack 编译源码所产生的文件变化在编译时,替换模块实现在运行时,两者如何联系起来?带着这两个问题,我们先简单看下 HMR 核心工作流程(简化版):HMR 工作流程图.png接下来开始 HMR 工作流程分析:当 Webpack(Watchman) 监听到项目中的文件/模块代码发生变化后,将变化通知 Webpack 中的构建工具(Packager)即 HMR Plugin;然后经过 HMR Plugin 处理后,将结果发送到应用程序(Application)的运行时框架(HMR Runtime);最后由 HMR Runtime 将这些发生变化的文件/模块更新(新增/删除或替换)到模块系统中。其中,HMR Runtime 是构建工具在编译时注入的,通过统一的 Module ID 将编译时的文件与运行时的模块对应起来,并且对外提供一系列 API 供应用层框架(如 React)调用。注意?:建议先理解上面这张图的大致流程,在进行后续阅读。放心,我等着大家~?四、HMR 完整原理和源码分析通过上一节内容,我们大概知道 HMR 简单工作流程,那么或许你现在可能还有很多疑惑:文件更新是什么通知 HMR Plugin?HMR Plugin 怎么发送更新到 HMR Runtime?等等问题。那么接下来我们开始详细结合源码分析整个 HMR 模块热更新流程,首先还是先看流程图,可以先不了解图中方法名称(红色字体黄色背景色部分):Webpack HMR.png上图展示了从我们修改代码,到模块热更新完成的一个 HMR 完整工作流程,图中已用红色阿拉伯数字符号将流程标识出来。要了解上面工作原理,我们先理解图中这几个名称概念:Webpack-dev-server :一个服务器插件,相当于 express 服务器,启动一个 Web 服务,只适用于开发环境;Webpack-dev-middleware :一个 Webpack-dev-server 的中间件,作用简单总结为:通过watch mode,监听资源的变更,然后自动打包。Webpack-hot-middleware :结合 Webpack-dev-middleware 使用的中间件,它可以实现浏览器的无刷新更新,也就是 HMR;下面一起学习 HMR 整个工作原理吧:1.监控代码变化,重新编译打包首先根据 devServer 配置,使用 npm start 将启动 Webpack-dev-server 启动本地服务器并进入 Webpack 的 watch 模式,然后初始化 Webpack-dev-middleware ,在 Webpack-dev-middleware 中通过调用 startWatch() 方法对文件系统进行 watch:当 startWatch() 方法执行后,便进入 watch 模式,若发现文件中代码发生修改,则根据配置文件对模块重新编译打包。2.保存编译结果Webpack 与 Webpack-dev-middleware 交互,Webpack-dev-middleware 调用 Webpack 的 API 对代码变化进行监控,并通知 Webpack 将重新编译的代码通过 JavaScript 对象保存在内存中。我们会发现,在 output.path 指定的 dist 目录并没有保存编译结果的文件,这是为什么?其实, Webpack 将编译结果保存在内存中,因为访问内存中的代码比访问文件系统中的文件快,这样可以减少代码写入文件的开销。Webpack 能将代码保存到内存中,需要归功于 Webpack-dev-middleware 的 memory-fs 依赖库,它将原本 outputFileSystem 替换成了 MemoryFileSystem 的实例,便实现代码输出到内存中。其中部分源码如下:上述代码先判断 fileSystem 是否是 MemoryFileSystem 的实例,若不是,则用 MemoryFileSystem 的实例替换 compiler 之前的 outputFileSystem。这样 bundle.js 文件代码就作为一个简单 JavaScript 对象保存在内存中,当浏览器请求 bundle.js 文件时,devServer 就直接去内存中找到上面保存的 JavaScript 对象并返回给浏览器端。3.监控文件变化,刷新浏览器Webpack-dev-server 开始监控文件变化,与第 1 步不同的是,这里并不是监控代码变化重新编译打包。当我们在配置文件中配置了 devServer.watchContentBase 为 true ,Webpack-dev-server 会监听配置文件夹中静态文件的变化,发生变化时,通知浏览器端对应用进行浏览器刷新,这与 HMR 不一样。4.建立 WS,同步编译阶段状态这一步都是 Webpack-dev-server 中处理,主要通过 sockjs(Webpack-dev-server 的依赖),在 Webpack-dev-server 的浏览器端(Client)和服务器端(Webpack-dev-middleware)之间建立 WebSocket 长连接。然后将 Webpack 编译打包的各个阶段状态信息同步到浏览器端。其中有两个重要步骤:发送状态Webpack-dev-server 通过 Webpack API 监听 compile 的 done 事件,当 compile 完成后,Webpack-dev-server 通过 _sendStats 方法将编译后新模块的 hash 值用 socket 发送给浏览器端。保存状态浏览器端将_sendStats 发送过来的 hash 保存下来,它将会用到后模块热更新。5.浏览器端发布消息当 hash 消息发送完成后,socket 还会发送一条 ok 的消息告知 Webpack-dev-server,由于客户端(Client)并不请求热更新代码,也不执行热更新模块操作,因此通过 emit 一个 “webpackHotUpdate” 消息,将工作转交回 Webpack。6.传递 hash 到 HMRWebpack/hot/dev-server 监听浏览器端 webpackHotUpdate 消息,将新模块 hash 值传到客户端 HMR 核心中枢的 HotModuleReplacement.runtime ,并调用 check 方法检测更新,判断是浏览器刷新还是模块热更新。如果是浏览器刷新的话,则没有后续步骤咯~~7.检测是否存在更新当 HotModuleReplacement.runtime 调用 check 方法时,会调用 JsonpMainTemplat免费云主机、域名e.runtime 中的 hotDownloadUpdateChunk (获取最新模块代码)和 hotDownloadManifest (获取是否有更新文件)两个方法,这两个方法的源码,在下一步展开。其中 hotEnsureUpdateChunk 方法中会调用 hotDownloadUpdateChunk :8.请求更新最新文件列表在调用 check 方法时,会先调用 JsonpMainTemplate.runtime 中的 hotDownloadManifest 方法, 通过向服务端发起 AJAX 请求获取是否有更新文件,如果有的话将 mainfest 返回给浏览器端。这边涉及一些原生 XMLHttpRequest,就不全部贴出了~9.请求更新最新模块代码在 hotDownloadManifest 方法中,还会执行 hotDownloadUpdateChunk 方法,通过 JSONP 请求最新的模块代码,并将代码返回给 HMR runtime 。然后 HMR runtime 会将新代码进一步处理,判断是浏览器刷新还是模块热更新。10.更新模块和依赖引用这一步是整个模块热更新(HMR)的核心步骤,通过 HMR runtime 的 hotApply 方法,移除过期模块和代码,并添加新的模块和代码实现热更新。从 hotApply 方法可以看出,模块热替换主要分三个阶段:鸿蒙官方战略合作共建——HarmonyOS技术社区找出过期模块 outdatedModules 和过期依赖 outdatedDependencies ; 2. 从缓存中删除过期模块、依赖和所有子元素的引用; 3. 将新模块代码添加到 modules 中,当下次调用 __webpack_require__ (webpack 重写的 require 方法)方法的时候,就是获取到了新的模块代码了。hotApply 方法执行之后,新代码已经替换旧代码,但是我们业务代码并不知道这些变化,因此需要通过 accept事件通知应用层使用新的模块进行“局部刷新”,我们在业务中是这么使用:11.热更新错误处理在热更新过程中,hotApply 过程中可能出现 abort 或者 fail 错误,则热更新退回到刷新浏览器(Browser Reload),整个模块热更新完成。到此,相信大家对“怎么理解Webpack HMR”有了更深的了解,不妨来实际操作一番吧!这里是云技术网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
相关推荐: 实用开源Javascript库中哪10大图像处理库值得推荐
实用开源Javascript库中哪10大图像处理库值得推荐,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。介绍对于很多人来说,使用Javascript来处理图像不是一件非常简单的事情,幸运的是我…