深刻理解webpack自动刷新浏览器

咱们在平常开发时,有一个须要在开发状态下的优化,就是浏览器能自动显示修改后的代码,而无需咱们手动刷新javascript

1. 自动刷新浏览器

为了能实现浏览器自动刷新,须要作两件事情:java

  • 监听文件变化
  • 自动刷新浏览器

1.1 监听文件变化

监听文件变化是在webpack模块进行。node

1.1.1 方式

须要在webpack中开启监听模式,有两种方式(开启监听模式后,能够设置监听相关配置watchOptions):webpack

1. 在webpack配置文件中添加watch:trueweb

module.export = {
  watch: true,
  watchOptions: {
    // 不监听的文件或文件夹
    ignored: /node_modules/,
    // 监听到变化发生后会等300ms再去执行动做,防止文件更新太快致使从新编译频率过高  
    aggregateTimeout: 300,  
    // 判断文件是否发生变化是经过不停的去询问系统指定文件有没有变化实现的
    poll: 1000
  }
}

2. 在执行启动 Webpack 命令时,带上 --watch 参数ajax

1.1.2 原理

  • 在 Webpack 中监听一个文件发生变化的原理是定时可在watchOptions.poll中设置)的去获取这个文件的最后编辑时间,每次都存下最新的最后编辑时间,若是发现当前获取的和最后一次保存的最后编辑时间不一致,就认为该文件发生了变化
  • 当发现某个文件发生了变化时,并不会马上告诉监听者,而是先缓存起来,收集一段时间(可在watchOptions.aggregateTimeout中设置)的变化后,再一次性告诉监听者。防止在编辑代码的过程当中可能会高频的输入文字致使文件变化的事件高频的发生

1.2 自动刷新浏览器

监听到文件变化后须要去刷新浏览器,这部分在webpack-dev-server模块中进行。(在使用 webpack-dev-server 模块去启动 webpack 模块时,webpack 模块的监听模式默认会被开启)api

1.2.1 原理

自动刷新有三种方法:浏览器

  • 借助浏览器扩展去经过浏览器提供的接口刷新
  • 往要开发的网页中注入代理客户端代码,经过代理客户端去刷新整个页面。
  • 把要开发的网页装进一个 iframe 中,经过刷新 iframe 去看到最新效果。

DevServer 支持第二、3种方法,第2种是 DevServer 默认采用的刷新方法。缓存

2. 模块热更新

以上自动刷新是会刷新整个页面,这种方式的缺点就是时间长,同时不能保存页面的状态。websocket

而模块热更新便可在不刷新整个页面的状况下来实时预览。它只会在代码发生变化时,只编译发生变化的模块,并替换浏览器中的老模块。

2.1 两种方式

如下两种方式都能实现模块热替换,区别在于其内部使用的通讯方式不一样。前者使用webcoket通讯,后者使用eventSource通讯。

2.1.1 webpack-dev-server

1. 开启方式

  • 开启DevServer的模块热替换模式: webpack-dev-server --hot
  • 添加HotModuleReplacementPlugin插件

2. 原理

参考
(1)webpack 对文件系统进行 watch 打包到内存中

  • 依赖webpack-dev-middleware,它会调用 webpack 的 api 对文件系统 watch
  • webpack-dev-middleware依赖memory-fs库,它将webpack 本来的 outputFileSystem 替换成了MemoryFileSystem 实例,这样代码就将输出到内存中

(2)devServer 通知浏览器端文件发生改变~~~~

  • 在启动 devServer 的时候,sockjs 在服务端和浏览器端创建了一个 webSocket 长链接
  • webpack-dev-server 调用 webpack api监听 compile的 done 事件,将编译打包后的新模块 hash 值发送到浏览器端

(3)webpack-dev-server/client 接收到服务端消息作出响应

  • webpack-dev-server默认修改了webpack 配置中的 entry 属性,在里面添加了 webpack-dev-client 的代码,这样在最后的 bundle.js 文件中就会有接收 websocket 消息的代码了。
  • webpack-dev-server/client 当接收到 type 为 hash 消息后会将 hash 值暂存起来,当接收到 type 为 ok 的消息后对应用执行 reload 操做(根据 hot 配置决定是刷新浏览器仍是对代码进行热更新(HMR)).

(4)webpack 接收到最新 hash 值验证并请求模块代码

  • webpack/hot/dev-server监听webpack-dev-server/client发出的webpackHotUpdate 消息。
  • 先调用hotDownloadManifest(ajax请求)来获取更新的文件列表。
  • 再调用hotDownloadUpdateChunk获取更新的新模块代码

(5)HotModuleReplacement.runtime 对模块进行热更新

  • 找出过时的模块和过时的依赖
  • 从缓存中删除过时的模块和依赖
  • 将新的模块添加到 modules 中

2.1.2 webpack-hot-middleware

1. 开启方式

  • Webpack配置添加HotModuleReplacementPlugin插件
  • Node Server引入webpack-dev-middlerware 和 webpack-hot-middleware插件(本人参与的项目中用到的是koa-webpack-middleware)
  • entry中注入热更新代码(必需要注入。为了保证服务端和客户端可以通讯)
    webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000

2. 原理
原理参考

相关文章
相关标签/搜索