ServiceWorker 更新方案

目录

  • 为什么加 serviceWorker 缓存

  • 加缓存后引发的问题

  • 探索强制更新方案

  • 实现细节

为什么加 serviceWorker 缓存

serviceWorker 具体用法可参考文章 [serviceWorker 实战]

下面通过几张图的对比来看下加缓存后的具体效果:

深圳请求广州服务器,请求距离近,不加缓存 51ms

深圳请求广州服务器,请求距离近,加缓存后 27ms

深圳请求南京服务器,请求距离远,不加缓存 106ms

深圳请求南京服务器,请求距离远,加缓存后 44ms

用 3G 网络,不加缓存 594ms

用 3G 网络,加缓存后 26ms

对比后发现:

  1. 不加缓存:html 请求时间,与服务器距离和网速有关,距离越远、网络越差耗时越多,在 50ms~600ms+

  2. 加缓存:html 请求时间,与服务器距离和网速有无关,稳定在 50ms 以内

结论:

加 serviceWorker 缓存可确保各地用户在网络不好的时候都能快速拿到 html

加缓存后引发的问题

缓存更新策略:

用户进入网页,没有缓存,通过网络请求 html,拿到结果后加入缓存

用户进入网页,有缓存后,先读取缓存的 html 去渲染执行,然后请求新的 html 去更新缓存

通过下面两张图来看下 serviceWorker 具体的更新机制:

存在的问题:

用户需要进 2 次网页才能看到最新的版本功能

探索强制更新方案

如何实现按需更新网页?探索了以下几个方案:

方案1-文件变更

最开始想到的方法:

发版的时候更新 serviceWorker.js 里面的版本号引起文件的变更从而使 serviceWorker 重新安装激活

执行顺序:fetch 请求 html => serviceWorker.register() => 发现变更重新安装激活

结论:方案行不通,html 的请求是最早的,而 serviceWorker 的注册、安装、激活更滞后

方案2-监听更新事件

监听 serviceWorker 的更新事件:

  1. 当 ServiceWorker installing 属性获取新的服务工作线程时,会触发 updatefound 事件

  2. 更新 serviceWorker.js 里面的版本号,引发重新安装激活,同时监听 updatefound 事件

  3. 发现有更新就出提示弹框,用户点击后,强制刷新浏览器更新

结论:方案可行,但是用户体验不好,用户需要手动点击强制刷新

方案3-自动刷页面

偷偷刷新页面:

用户进入页面后,出 loading,自动去刷新 1 次页面

可以前端自己强刷 1 次

内嵌在客户端的可以让客户端容器强刷 1 次

结论:体验不好

方案4-配置文件

在 fetch 里做拦截,比较远程配置:

fetch 拦截时机最早,拦截 html 请求的时候,先去请求1个远程配置文件

然后比较配置文件里的版本号和缓存的版本号,一致走缓存,不一致走网络请求

请求远程配置文件会有一定耗时,耗时过久会抵消缓存产生的效益

结论:方案可行,需要控制住配置文件请求耗时

方案5-URL标识

在 fetch 里做拦截,比较 url:

fetch 拦截时机最早

需要强制刷新的时候,修改访问链接 url 携带的标识字段值

fetch 拦截 html 请求的时候,通过比较 url 标识和缓存标识,一致走缓存,不一致走网络请求

需要具备变更 url 的条件(比如由内嵌容器控制入口和变更)

结论:方案可行,需要 url 具备可变更条件

实现细节

因为项目内嵌在客户端容器里,支持动态拼接修改 url,所以用的是方案5

下面看下具体实现:

实现逻辑

  1. 网站核心入口是 html,资源类型为 document

  2. 客户端控制在跳对应网站的时候,url 上拼接 readerVersion=new1

  3. serviceWorker fetch 拦截 html,判断缓存的 readerVersion 值和 url 上的值是否一致:

  • 一致,走本地缓存,同时更新 serviceWorker 的缓存

  • 不一致,走网络请求,请求成功后更新 serviceWorker 的缓存

  • 网络请求失败走 serviceWorker 的旧缓存兜底

具体操作

  1. 前端代码发布上线,此时 readerVersion => ''

  2. 配置平台修改 readerVersion => new1+

  3. 上线完毕,看数据大部分用户更新后,可恢复配置 readerVersion => '',也可不恢复

注意事项

  1. 强制更新客户端 readerVersion=new1 每次需要加 1,new1 => new2

  2. fetch 拦截 html 请求需要排除 favicon.ico,服务器会自动请求此图标链接,同样返回 html

相关推荐
风逸hhh1 小时前
python打卡day29@浙大疏锦行
开发语言·前端·python
LuckyLay1 小时前
Vue百日学习计划Day33-35天详细计划-Gemini版
前端·vue.js·学习
ᖰ・◡・ᖳ1 小时前
JavaScript:PC端特效--缓动动画
开发语言·前端·javascript·css·学习·html5
会飞的鱼先生2 小时前
vue2、vue3项目打包生成txt文件-自动记录打包日期:git版本、当前分支、提交人姓名、提交日期、提交描述等信息 和 前端项目的版本号json文件
前端·vue.js·git·json
!win !3 小时前
uni-app项目从0-1基础架构搭建全流程
前端·uni-app
c_zyer3 小时前
使用 nvm 管理 Node.js 和 npm 版本
前端·npm·node.js
布Coder3 小时前
前端 vue + element-ui 框架从 0 - 1 搭建
前端·javascript·vue.js
i_am_a_div_日积月累_4 小时前
Element Plus 取消el-form-item点击触发组件,改为原生表单控件
前端·vue.js·elementui
集成显卡4 小时前
网页 H5 微应用接入钉钉自动登录
前端·后端·钉钉
paintstar4 小时前
el-scrollbar 获取滚动条高度 并将滚动条保持在低端
前端·学习·vue·css3