Service Workers(PWA初体验)

简介: 在前端越来越重的这个时代,页面加载速度成为了一个重要的指标。对于这个问题,业界也有一些解决方案。浏览器缓存、协议缓存、强缓存懒加载(首屏)CDN 多域名突破下载并发限制。其实在两年前内部就对这块内容做过调研了。appCache方案?PWA方案?但是最后都没选择。之前看代码,发现是 localstroage 存代码,如果有就拿 localstroage 去用。省去了这一部分加载的时间。上个同事离职了。当时的调研结果我也忘了。只能再开始新一轮的调研,我选择的是 PWA 方案。网上的资料很少。我希望我可以写一篇帮助下一个想使用 PWA 方案的人。

Service Workers


Service worker是一个注册在指定源和路径下的事件驱动worker


Service worker运行在worker上下文,因此它不能访问DOM。不同于主线程,它运行在其他线程中,所以不会造成主线程阻塞。它设计为完全异步,同步API(如XHR和localStorage)不能在service worker中使用。


Service workers 本质上充当Web应用程序(服务端)与浏览器(客户端)之间的代理服务器。


可以提供有效有效的离线体验,拦截网络请求。还可以推送通知。


Service Workers 需要注意的地方


  1. 需要支持 HTTPS 访问你的页面。出于安全原因,Service Workers 要求必须在 HTTPS 下才能运行。(其实好多API都需要HTTPS的支持)


  1. 资源路径为根目录的绝对路径。最大作用域 (scope),为资源路径。
    https://www.lilnong.top/static/js/sw-20190621.js的最大作用路径为/static/js/


  1. 为了便于本地开发,localhost 也被浏览器认为是安全源。


  1. 在已经支持 serivce workers 的浏览器的版本中,很多特性没有默认开启。如果你发现示例代码在当前版本的浏览器中怎么样都无法正常运行,你可能需要开启一下浏览器的相关配置:


Firefox Nightly: 访问 about:config 并设置 dom.serviceWorkers.enabled 的值为 true; 重启浏览器;


Chrome Canary: 访问 chrome://flags 并开启 experimental-web-platform-features; 重启浏览器 (注意:有些特性在Chrome中没有默认开放支持);


Opera: 访问 opera://flags 并开启 ServiceWorker 的支持; 重启浏览器。


service worker 声明周期


  1. 下载


  1. 首次访问service worker控制的网站或页面时,service worker会立刻被下载。
  2. 至少每24小时它会被下载一次。


2.安装

  1. 首次下载会尝试安装,
  2. 下载的文件是新的,尝试进行安装


3.激活

  1. 安装成功后它会被激活
  2. 如果现有service worker已启用,新版本会在后台安装,但不会被激活,这个时序称为worker in waiting
  3. 直到所有已加载的页面不再使用旧的service worker才会激活新的service worker。新的service worker会被激活(成为active worker)。


我们页面引入sw.js内容为a。当我们修改为b


这时候ab都是已经安装完毕的,但是a是当前正在用的。b需要等没有页面在用a,才会进入激活状态。


bVbuiis.webp.jpg


Cache


Cache 为缓存的 Request/Response 对象对提供存储机制。


当前我们作为 ServiceWorker 生命周期的一部分。尽管它被定义在 service worker 的标准中, 但是它不必一定要配合 service worker 使用。也暴露在 window 作用域下的。


  1. Cache.add(request)


request 是一个字符串类型的 URL。如


cache.add('https://www.lilnong.top/static/css/normalize-8.0.0.css')
功能上等于调用 fetch(), 然后使用 Cache.put()response 添加到 cache 中。


  1. Cache.addAll(requests)
    功能同上,只不过入参为字符串数组


  1. Cache.match(request, options)返回一个Promise对象,resolve的结果是跟Cache对象匹配已经缓存的请求。requres同上,是要匹配的URLoptions如下


a.ignoreSearch: 设置是否忽略url中的query。该选项默认为 false


b.ignoreMethod: true匹配时就不会验证 Request 对象的 http 方法 (通常只允许是 GETHEAD 。) 该参数默认值为 false。


c.ignoreVary: 为 true 时匹配不进行 VARY 部分的匹配。例如,如果一个URL匹配,此时无论Response对象是否包含VARY头部,都会认为是成功匹配。该参数默认为 false。


d.cacheName: 一个 DOMString ,代表一个具体的要被搜索的缓存。注意该选项被 Cache.match()方法忽略。


  1. Cache.matchAll(request, options)
    同上,返回一个Promise 对象,resolve的结果是跟Cache对象匹配的所有请求组成的数组


  1. Cache.put(request, response)
    人为的,为一个URL设置response


  1. Cache.delete(request, options)


搜索条目。如果找到,则删除该Cache 条目,并且返回一个resolvetruePromise对象;如果未找到,则返回一个resolvefalsePromise对象。


  1. Cache.keys(request, options)
    返回一个Promise对象,resolve的结果是Cache对象key(request 对象)组成的数组。


ServiceWorker 的使用


  1. serviceWorkerContainer.register() 来注册


  1. 注册成功的话,会开启另一个线程来做这件事。与我们的网页是互不相干的。


  1. service worker 现在可以接收事件。


  1. service worker 控制的页面打开后会尝试去安装 service worker


  1. 最先发送给 service worker 的事件是安装事件(在这个事件里可以开始进行填充 IndexDB和缓存站点资源),让所有资源可离线访问。


  1. oninstall 事件的处理程序执行完毕后,可以认为 service worker 安装完成了。


  1. service worker 安装完成后,会接收到一个激活事件 onactivate 主要用途是清理先前版本的 service worker 脚本中使用的资源。


  1. Service Worker 现在可以控制页面了,但仅是在 register() 成功后的打开的页面。


ServiceWorker 的注册


if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw-test/sw.js', { scope: '/sw-test/' }).then(function(reg) {
    // registration worked
    console.log('Registration succeeded. Scope is ' + reg.scope);
  }).catch(function(error) {
    // registration failed
    console.log('Registration failed with ' + error);
  });
}


相关文章
|
Prometheus Cloud Native Unix
完全解读Prometheus查询(上)
完全解读Prometheus查询(上)
577 0
|
Docker 容器
docker如何在容器外执行容器内命令
有时候我们想执行某个容器的某条命令,但又不想进入容器内。那该怎么办? 所以就有一种办法,我们直接在容器外执行容器内的命令,来进行一些容器内的操作。
3169 0
docker如何在容器外执行容器内命令
|
Web App开发 JavaScript Java
浏览器同域名请求的最大并发数限制
  当我们在浏览网页的时候,对浏览速度有一个重要的影响因素,就是浏览器的并发数量。并发数量简单通俗的讲就是,当浏览器网页的时候同时工作的进行数量。   如果同时只有2个并发连接数数量,那网页打开的时候只能依赖于这2条线程,前面如果有打开慢的内容,就会直接影响到后面的内容打开。
7077 0
|
Linux 网络安全
树莓派开发笔记(十一):蓝牙的使用,BlueZ协议(双树莓探测rssi并通过蓝牙互传获取的rssi信号强度)
树莓派开发笔记(十一):蓝牙的使用,BlueZ协议(双树莓探测rssi并通过蓝牙互传获取的rssi信号强度)
树莓派开发笔记(十一):蓝牙的使用,BlueZ协议(双树莓探测rssi并通过蓝牙互传获取的rssi信号强度)
|
机器学习/深度学习 算法 数据挖掘
线性回归模型的原理、实现及应用,特别是在 Python 中的实践
本文深入探讨了线性回归模型的原理、实现及应用,特别是在 Python 中的实践。线性回归假设因变量与自变量间存在线性关系,通过建立线性方程预测未知数据。文章介绍了模型的基本原理、实现步骤、Python 常用库(如 Scikit-learn 和 Statsmodels)、参数解释、优缺点及扩展应用,强调了其在数据分析中的重要性和局限性。
866 3
|
Python
使用 Python 合并微信与支付宝账单,生成财务报告
这篇博客介绍了如何使用 Python 脚本合并微信与支付宝账单数据,生成自动化财务报告。通过 pandas 库,学习如何清洗、合并和分析账单数据,以及如何生成 Markdown 格式的财务报告。
|
存储 安全 前端开发
在前端开发中需要考虑的常见web安全问题和攻击原理以及防范措施
在前端开发中需要考虑的常见web安全问题和攻击原理以及防范措施
1920 0
|
域名解析 缓存 网络协议
中间人攻击之DNS欺骗
【8月更文挑战第13天】
1308 2
|
存储 easyexcel 中间件
【Alibaba中间件技术系列】「EasyExcel实战案例」实战研究一下EasyExcel如何从指定文件位置进行读取数据
【Alibaba中间件技术系列】「EasyExcel实战案例」实战研究一下EasyExcel如何从指定文件位置进行读取数据
832 88
|
监控 JavaScript 前端开发
前端监控实战之 New Relic
前端监控实战之 New Relic
745 0