代码配置
在 webpack.config.js 文件中设置 devServer.hot 为 true,启用 HMR 特性。另外要用上 HMR 特性则还需要配置 HotModuleReplacementPlugin 插件。如果不想配置这个插件,也可以在 webpack-dev-server 启动时添加了 —hot
这个参数,这样 HotModuleReplacementPlugin 插件会被自动配置进来。
问自己的问题
- 通过 webpack HMR 进行开发的过程中,并没有在 dist 目录中找打 wegpack 打包好的文件,它们去哪儿了?
- webpack-dev-server 中依赖的 webpack-dev-middleware 扮演了什么角色。
- 通过 Chrome 开发者工具我知道浏览器是通过 websocket 和 webpack-dev-server 进行通信的,但是 websocket 和 message 中并没有发现新模块代码。打包后的新模块又是通过什么方式发送到浏览器端的呢?为什么新的模块不通过 websocket 随消息一起发送到浏览器端呢?
- 当模块的热替换过程中,如果替换模块失败,有什么回退机制吗?
各个模块的职责
- Webpack
- 在 webpack 的 watch 模式下,文件系统中某一个文件发生修改,webpack 监听到文件变化,根据配置文件对模块重新编译打包,并将打包后的代码通过简单的 JavaScript 对象保存在内存中。
- webpack/hot/dev-server 的工作根据 webpack-dev-server/client 传给它的信息以及 dev-server 的配置决定是刷新浏览器呢,还是进行模块热更新。
- webpack-dev-server
- 依赖的 webpack-dev-middleware 和 webpack 之间的交互,webpack-dev-middleware 调用 webpack 暴露的接口对代码变化进行监控,并且告诉 webpack,将代码打包到内存中。
- webpack-dev-server/client 端并不能够请求更新的代码,也不会执行热更新模块操作,而把这些工作交给了 webpack。
- webpack-dev-server 与 webpack-dev-server/client(浏览器端)通过 sockjs 进行 websocket 通信。
- HotModuleReplacementPlugin
- HMRPlugin.runtime 是客户端 HMR 的中枢,它接收到上一步传给它的新模块的 hash 值,通过 JsonpModuleTemplate.runtime 向 webpack-dev-server 端发送 ajax 请求,server 端返回一个 json,该 json 包含了所有要更新模块的 hash 值,获取到更新列表后,该模块再次通过 jsonp,获取到更新的模块代码。
- HotModuleReplacementPlugin 将会对新旧模块进行对比,决定是否更新模块,在决定更新模块后,检查模块之间的依赖关系,更新模块的同事更新模块间的依赖引用。
- 当 HMR 失败后,回退到 live reload 操作,也就是进行浏览器刷新来获取最新的打包代码。
具体的步骤
图源来自:Webpack HMR 原理解析 - 知乎
- webpack 在 watch 模式下,对文件系统进行监听,并把文件打包到内存。
- webpack-dev-server 监听到文件变化后,通过 sockjs websocket 通信,通知浏览器端发生改变。
- webpack-dev-server 在打包的 bundle.js 中添加了 webpack-dev-server/client 的代码,webpack-dev-server/client 接收到 webpack-dev-server 发过来的消息。根据 hot 的配置,是重刷新页面,还是进行热更新。
- 如果是热更新,通过 webpack/hot/emitter 通知 webpack/hot/dev-server。调用 webpack/lib/HotModuleReplacementPlugin.runtime 的 check 方法,检查是否有更新。
- 在 check 过程中,会调用两个方法:hotDownloadManifest(根据之前的 hash 值调用 ajax 向服务端请求是否更新的文件)和 hotDownloadUpdateChunk(如果有更新,通过 jsonp 请求最新的模块代码,并将代码返回给 HMR runtime)。HMR runtime 会根据返回的新模块的代码做进一步处理,可能是刷新页面,也可能是对模块进行热更新。
- HMR.runtime 对模块进行热更新,这一步是关键。其中最主要是 hotApply 方法。
- 第一阶段找出 outdateModules 和 outdatedDependencies
- 删除模块对应的缓存
- 删除模块对应的依赖
- 将模块添加到 modules 中,当下次调用 webpack_require 方法的时候,就是获取到了新的模块代码了。
- 更新模块缓存
- 如果过程中出现错误,热更新将回退到刷新浏览器。
- 业务代码需要做些什么?当用新的模块代码替换老的模块后,我们的业务代码并不知道模块代码发生了变化。我们要在 index.js 文件中 HMR 的 accept 方法,添加模块更新后的处理函数,及时将 hello 方法的返回值插入到页面中。
- 调用 react-hot-loader 的 hot 方法,包裹一下最上层的 App 组件:hot(module)(App)。
封面图片 by James Harrison on Unsplash
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!