Service Worker一问一答

2018-08-14 admin

PWA的核心在于Service Worker,目前中文社区中关于Service Worker的知识深度普遍不够,难以应对实际项目中的问题。例如我想要知道在卸载sw(下文简称sw)后需不需要手动清理caches,搜索引擎是没有什么好答案的。这篇文章结合淘宝首页PWA的经验,分享出我认为非常有价值的关于Service Worker的知识点。

先从注册说起,sw应该在什么时候注册?

一些教程是这样注册sw的

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
}

这样做会造成第一个问题,sw线程将加剧对CPU和内存的使用,并且sw内预缓存的资源是需要下载的,移动设备带宽有限,sw线程占用的同时,主进程带宽就变成了小水管了。

首次打开各种资源都非常宝贵,况且是渐进式,完全没有必要争第一次打开页面就要缓存资源。正确的做法是,页面加载完以后sw的事。

if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('/sw.js');
  });
}

我想注销所有已注册用户的sw,怎么做才最稳妥?

并不是所有移动端浏览器都支持getRegistrations,getRegistration更靠谱,可以先尝试使用getRegistrations,如果无法使用再尝试getRegistration,如下。

var serviceWorker = navigator.serviceWorker;

serviceWorker.getRegistrations ? serviceWorker.getRegistrations().then(function(sws) {
  sws.forEach(function(sw) {
    sw.unregister();
  });
}) : serviceWorker.getRegistration && serviceWorker.getRegistration().then(function(sw) {
  sw && sw.unregister();
});

我注销了sw,之前留下的caches还需要自己动手处理吗?

需要,cacheStorage虽然属于PWA规范API当中,但它是独立的,虽然注销了service worker,caches里垃圾不清掉,它就会一直留在那里了。这么清

window.caches && caches.keys && caches.keys().then(function(keys) {
  keys.forEach(function(key) {
    caches.delete(key);
  });
});

该不该使用self.clients.claim?

clients.claim的作用是使当前SW接管已经打开的所有标签页,使用场景是用户首次打开注册sw的页面时,还存在其他同域页面的浏览器标签的情况。之前打开的页面没有被接管,所以通过clients.claim接管已经打开但没受到控制的浏览器标签页面。

skipWaiting的使用场景是在sw更新时,因为有上一个sw正在控制着所有该站点的页面,新的sw在active后进入waiting状态,直到用户将所有该站点页面关闭,新的sw才上位。这跟Chrome和VScode的更新机制一样,在使用过程中有更新的时候,并不影响你继续使用老版本,而是在重启程序后,直接才变成新版。通过skipWaiting方法,可以直接让waiting状态的新sw替换掉老的sw,注意 还会自动接管上一个sw管辖的页面

我是不推荐使用clients.claim的,首先出现不受控标签的情况相对比较少,况且首次加载速度尤其重要,能省点开销就省点吧。

在sw里监听fetch事件,请求多过了一层sw,会有性能损耗吗?

当然会,像下面这样搞,是万万不要的

self.addEventListener('fetch', event => {
  event.respondWith(fetch(event.request));
});

为什么我在sw中postMessage到页面,页面无法收到message

这是在测试serviceWorker的postMessage能力时,经常遇到的一个问题,想要找到原因就要从sw接管的页面说起。在sw.js中使用self.clients.matchAll方法获取当前serviceWorker实例所接管的所有标签页,注意是当前实例 已经接管的,并且sw.js中的代码只会执行一次,当sw.js代码中存在如下代码时

self.clients.matchAll()
  .then(function (clients) {
    clients.forEach(client => {
      client.postMessage('这条消息不会被收到');
    })
  });

clients一定是个空数组,所以永远也postMessage不到页面。那要如何才能在首次install就postMessage到页面上那?答案是self.skipWaiting,然后在activate事件中使用self.clients.matchAll,因为调用了skipWaiting,当前的sw在install以后会立刻avtivate并接管上一个sw的所有标签页,这样就能在新sw中拿到标签页postMessage了

self.skipWaiting()
self.addEventListener('activate', () => {
  self.clients.matchAll()
    .then(function (clients) {
      clients.forEach(client => {
        client.postMessage('skipWaiting让新的sw接管了页面,这样就可以收到');
      })
    });
})

[转载]原文链接:https://segmentfault.com/a/1190000015999229

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-37941.html

文章标题:Service Worker一问一答

相关文章
service worker的思考
对service worker的思考 <a id=“more”></a> what? Chrome 提出和力推的一个 WEB API,用于给 web 应用提供高级的可持续的后台处理能力。该 WEB API 标准起草...
2018-06-05
使用 Web Worker 实现简单的非阻塞异步
之前的文章提到了 JavaScript 中的异步编程,然而无论早就存在的 setTimeout 还是 ES6 中的 Promise,它们都是 阻塞 异步,执行函数的时候,会阻塞线程。setTimeout 只会把一个函数延后执行,但还是在主线...
2017-12-25
Service Workers, Web Workers 与 WebSockets 的区别
As fairly-new web technologies, Service Workers, Web Workers and WebSockets all started, stalled, and then sort of made ...
2018-02-28
Service worker (@nuxtjs/workbox) 采坑记
PWA(Progressive Web App)是前端的大趋势,它能极大的加快前端页面的加载速度,得到近乎原生 app 的展示效果(其实难说)。PWA 其实是多种前端技术的组合,其中最重要的一个技术就是 service worker。 Se...
2018-09-21
搞笑向, 面向IE8的webworker-ployfill
首先,这是一篇不严谨的博文。 本文仅供参考,无法在实际生产中运用。 在捯饬文件分片上传的过程中,我总是觉得单线程太慢了。 于是想,用webWorker呗。 首先,我们可以查看一下WebWorker的兼容性。根据MDN文档来看,主流浏览器都兼...
2018-06-22
浏览器缓存、CacheStorage、Web Worker 与 Service Worker
前言 最近在翻红宝书,看到 Web Worker 那章,猛然意识到,通过它竟然可以把几个缓存相关的概念串起来,甚是有趣,撰文记之。最后我也写了一个完整的离线应用 Demo,以供运行调试。 浏览器缓存 传统意义上的浏览器缓存,分为强缓存和协商...
2018-02-08
multiple web workers的实现
一. 背景 先交代下业务背景,去年十月做了一个视频上传的相关业务,部分需求如下: 视频文件的MD5计算 并行上传,可配置最大并行数。 分片上传 可随时中断,取消上传。 以上只是上传部分的功能,对于我这种第一次做上传的人来说,看了真是一头...
2018-10-24
Service Worker Cookbook | 由 Mozilla 及贡献者共同撰写的一本关于 Service Worker 的实用指南
It’s online. It’s offline. It’s a Service Worker! Service workers are a new technology to aid developers in: - creati...
2018-05-28
离屏Canvas — 解耦DOM,用Web Worker来优化性能
现在因为有了离屏Canvas,你可以不用在你的主线程中绘制图像了! Canvas 是一个非常受欢迎的表现方式,同时也是WebGL的入口。它能绘制图形,图片,展示动画,甚至是处理视频内容。它经常被用来在富媒体web应用中创建炫酷的用户界面或者...
2018-09-05
如何优雅地结合Rxjs和WebWorker
在项目中同时使用rxjs和webworker的场景并不多,所以相关的资料也较少,恰巧我在开发项目时遇到了很适合使用这两项技术的场景,所以尝试着将其结合起来使用,也收到了很不错的效果,所以分享一下自己的使用经验和心得。 同时也专门写了将两者相...
2018-08-03
回到顶部