摘要:的核心在于,目前中文社区中关于的知识深度普遍不够,难以应对实际项目中的问题。通过方法,可以直接让状态的新替换掉老的,注意还会自动接管上一个管辖的页面。
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接管了页面,这样就可以收到"); }) }); })
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/108132.html
摘要:业界动态发布版本,同时发布了版本以及首个稳定版本的。程序人生如何用人类的方式进行二关于如何在中进行良好的沟通,避免陷入一些潜在的陷阱。技术周刊由小组出品,汇聚一周好文章,周刊原文。 业界动态 Angular 5.1 & More Now Available Angular发布5.1版本,同时发布了Angular CLI 1.6版本以及首个稳定版本的Angular Material。CL...
摘要:一阅前热身为了更加形象的说明同步异步阻塞非阻塞,我们以小明去买奶茶为例。等奶茶做好了,店员喊一声小明,奶茶好了,然后小明去取奶茶。将响应结果发给相应的连接请求处理完成因为基于,所以每个可以处理无数个连接请求。如此,就轻松的处理了高并发。 一、阅前热身 为了更加形象的说明同步异步、阻塞非阻塞,我们以小明去买奶茶为例。 1、同步与异步 ①同步与异步的理解 同步与异步的重点在消息通知的方式上...
摘要:一阅前热身为了更加形象的说明同步异步阻塞非阻塞,我们以小明去买奶茶为例。等奶茶做好了,店员喊一声小明,奶茶好了,然后小明去取奶茶。将响应结果发给相应的连接请求处理完成因为基于,所以每个可以处理无数个连接请求。如此,就轻松的处理了高并发。 一、阅前热身 为了更加形象的说明同步异步、阻塞非阻塞,我们以小明去买奶茶为例。 1、同步与异步 ①同步与异步的理解 同步与异步的重点在消息通知的方式上...
阅读 3479·2021-11-19 09:40
阅读 1493·2021-10-13 09:41
阅读 2658·2021-09-29 09:35
阅读 2712·2021-09-23 11:21
阅读 1696·2021-09-09 11:56
阅读 831·2019-08-30 15:53
阅读 846·2019-08-30 15:52
阅读 600·2019-08-30 12:47