Service Worker一问一答

Service Worker

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接受了页面,如许就能够收到');
      })
    });
})
    原文作者:GeoffZhu
    原文地址: https://segmentfault.com/a/1190000015999229
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞