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

相关推荐
m0_587383001 小时前
碰碰好评卡功能落地全流程实战指南 附核心逻辑与常见问题解决方案
java·前端·数据库·后端·struts·需求分析
子轩学长说1 小时前
Workbuddy独立文件浏览器新上线,彻底告别WPS和office全家桶~
前端
nyaomaru1 小时前
如何用 Jev 从 PR 中提取 “Why” 并写入 CHANGELOG?🤔
前端·typescript
Shirley~~1 小时前
从0搭建一个3D立体场景:光影与交互全解析
前端·3d
Dovis(誓平步青云)1 小时前
一年1956亿行:智能电表场景下的时序数据存储实践
运维·前端·自动化·音视频·prometheus
兰亭妙微UI设计公司1 小时前
兰亭妙微分享:高手设计登录页的12种切入点
开发语言·前端·javascript
前端Baymax1 小时前
静默的 86 小时:全链 402 停摆与零告警的故障复盘
开发语言·前端·javascript
要开心吖ZSH1 小时前
定时任务从外部调度搬回本地 @Scheduled:一次连接池被打满的复盘与选型思考
前端·firefox
不停喝水1 小时前
【前端转全栈java速通课】 项目实战④12-14节 拦截器过滤器和全局配置-cors跨域设置-token体系-利用session做验证码
java·开发语言·前端·ai·容器
VimorphTech1 小时前
转写结果怎么生成双语字幕?TypeScript 实现 SRT、WebVTT 与索引匹配
javascript·音视频开发