webpack 热更新实现原理

webpack-dev-server启动本地服务

根据webpack-dev-server的package.json中的bin命令,可以找到命令的入口文件bin/webpack-dev-server.js。

webpack-dev-server 会启动 webpack 创建 compiler 实例,然后在本地启动两个服务:一个 express 静态资源服务,用来接收浏览器发送的资源请求和发送资源;一个 websocket 服务,用来和浏览器进行双向通信。

修改 entry 配置

首先通过启动 webpack-dev-server 会修改 webpack.config.js 的 entry 配置,新增两个入口文件:

  • webpack-dev-server/client/index.js
  • webpack/hot/dev-server.js

webpack-dev-server/client/index.js 包含的是客户端向服务端通信的相关代码。

webpack/hot/dev-server.js 包含的是客户端进行检查和热更新的相关代码。

监听 webpack 编译结束

监听 webpack 的 done 钩子。当 webpack 编译结束后,会向浏览器发送通知,触发浏览器的 hash 和 ok 事件。

监听文件变化

使用 webpack-dev-middleware 监听本地文件的变化,如果文件发生了变化就会立刻对文件代码进行编译和打包,然后将编译后的文件写入到内存中。

浏览器接收到热更新通知

在 webpack-dev-server/client/index.js 中包含定义的 hash 和 ok 事件。hash 事件会接收服务端发送过来的最新hash,然后赋值给currentHash变量保存在本地。ok 事件会触发在 webpack/hot/dev-server.js 中定义的 module.hot.check 方法进行热更新检查。

module.hot.check

首先会利用上一次更新的 hash 值向服务端发送 ajax 请求,获取 name.hash.hot-update.json 文件。该文件中包含需要热更新的模块和下次热更新的 hash 值。
然后再通过 jsonp 的方式向服务端请求 name.hash.hot-update.js 文件,该 js 文件中包含的就是变更文件编译后的模块代码。当浏览器拿到 js 文件后会立刻执行 js 文件的代码。

该 js 文件中还包含一个 webpackHotUpdate 方法,webpackHotUpdate 方法主要做三个工作:

  • 删除过期的模块和它相关依赖
  • 将新的模块添加到 modules 中
  • 通过 webpack_require 执行模块相关的代码

如果在热更新检查的过程中发生错误,导致热更新失败,最终会调用 window.location.reload 方法执行浏览器的刷新。

module.hot.accept

我们知道在 module.hot.check 方法中会通过 webpakc_require 执行更新模块相关的代码。但是执行代码的过程中并不会进行浏览器的渲染。
所以开发者可以在文件中手动添加当指定模块进行热更新后在页面需要进行更新的代码。就是使用 module.hot.accept 方法指定模块路径和最新模块代码应用到运行环境的函数。

posted @ 2024-08-20 17:41  Rocen  阅读(126)  评论(0)    收藏  举报