摘要:的核心在于,目前中文社區(qū)中關(guān)于的知識(shí)深度普遍不夠,難以應(yīng)對(duì)實(shí)際項(xiàng)目中的問(wèn)題。通過(guò)方法,可以直接讓狀態(tài)的新替換掉老的,注意還會(huì)自動(dòng)接管上一個(gè)管轄的頁(yè)面。
Service Worker
PWA的核心在于Service Worker,目前中文社區(qū)中關(guān)于Service Worker的知識(shí)深度普遍不夠,難以應(yīng)對(duì)實(shí)際項(xiàng)目中的問(wèn)題。例如我想要知道在卸載sw(下文簡(jiǎn)稱(chēng)sw)后需不需要手動(dòng)清理caches,搜索引擎是沒(méi)有什么好答案的。這篇文章結(jié)合淘寶首頁(yè)P(yáng)WA的經(jīng)驗(yàn),分享出我認(rèn)為非常有價(jià)值的關(guān)于Service Worker的知識(shí)點(diǎn)。先從注冊(cè)說(shuō)起,sw應(yīng)該在什么時(shí)候注冊(cè)?
一些教程是這樣注冊(cè)sw的
if ("serviceWorker" in navigator) { navigator.serviceWorker.register("/sw.js") }
這樣做會(huì)造成第一個(gè)問(wèn)題,sw線(xiàn)程將加劇對(duì)CPU和內(nèi)存的使用,并且sw內(nèi)預(yù)緩存的資源是需要下載的,移動(dòng)設(shè)備帶寬有限,sw線(xiàn)程占用的同時(shí),主進(jìn)程帶寬就變成了小水管了。
首次打開(kāi)各種資源都非常寶貴,況且是漸進(jìn)式,完全沒(méi)有必要爭(zhēng)第一次打開(kāi)頁(yè)面就要緩存資源。正確的做法是,頁(yè)面加載完以后sw的事。
if ("serviceWorker" in navigator) { window.addEventListener("load", function() { navigator.serviceWorker.register("/sw.js"); }); }我想注銷(xiāo)所有已注冊(cè)用戶(hù)的sw,怎么做才最穩(wěn)妥?
并不是所有移動(dòng)端瀏覽器都支持getRegistrations,getRegistration更靠譜,可以先嘗試使用getRegistrations,如果無(wú)法使用再?lài)L試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(); });我注銷(xiāo)了sw,之前留下的caches還需要自己動(dòng)手處理嗎?
需要,cacheStorage雖然屬于PWA規(guī)范API當(dāng)中,但它是獨(dú)立的,雖然注銷(xiāo)了service worker,caches里垃圾不清掉,它就會(huì)一直留在那里了。這么清
window.caches && caches.keys && caches.keys().then(function(keys) { keys.forEach(function(key) { caches.delete(key); }); });該不該使用self.clients.claim?
clients.claim的作用是使當(dāng)前SW接管已經(jīng)打開(kāi)的所有標(biāo)簽頁(yè),使用場(chǎng)景是用戶(hù)首次打開(kāi)注冊(cè)sw的頁(yè)面時(shí),還存在其他同域頁(yè)面的瀏覽器標(biāo)簽的情況。之前打開(kāi)的頁(yè)面沒(méi)有被接管,所以通過(guò)clients.claim接管已經(jīng)打開(kāi)但沒(méi)受到控制的瀏覽器標(biāo)簽頁(yè)面。
skipWaiting的使用場(chǎng)景是在sw更新時(shí),因?yàn)橛猩弦粋€(gè)sw正在控制著所有該站點(diǎn)的頁(yè)面,新的sw在active后進(jìn)入waiting狀態(tài),直到用戶(hù)將所有該站點(diǎn)頁(yè)面關(guān)閉,新的sw才上位。這跟Chrome和VScode的更新機(jī)制一樣,在使用過(guò)程中有更新的時(shí)候,并不影響你繼續(xù)使用老版本,而是在重啟程序后,直接才變成新版。通過(guò)skipWaiting方法,可以直接讓waiting狀態(tài)的新sw替換掉老的sw,注意 還會(huì)自動(dòng)接管上一個(gè)sw管轄的頁(yè)面。
我是不推薦使用clients.claim的,首先出現(xiàn)不受控標(biāo)簽的情況相對(duì)比較少,況且首次加載速度尤其重要,能省點(diǎn)開(kāi)銷(xiāo)就省點(diǎn)吧。
在sw里監(jiān)聽(tīng)fetch事件,請(qǐng)求多過(guò)了一層sw,會(huì)有性能損耗嗎?當(dāng)然會(huì),像下面這樣搞,是萬(wàn)萬(wàn)不要的
self.addEventListener("fetch", event => { event.respondWith(fetch(event.request)); });為什么我在sw中postMessage到頁(yè)面,頁(yè)面無(wú)法收到message
這是在測(cè)試serviceWorker的postMessage能力時(shí),經(jīng)常遇到的一個(gè)問(wèn)題,想要找到原因就要從sw接管的頁(yè)面說(shuō)起。在sw.js中使用self.clients.matchAll方法獲取當(dāng)前serviceWorker實(shí)例所接管的所有標(biāo)簽頁(yè),注意是當(dāng)前實(shí)例 已經(jīng)接管的,并且sw.js中的代碼只會(huì)執(zhí)行一次,當(dāng)sw.js代碼中存在如下代碼時(shí)
self.clients.matchAll() .then(function (clients) { clients.forEach(client => { client.postMessage("這條消息不會(huì)被收到"); }) });
clients一定是個(gè)空數(shù)組,所以永遠(yuǎn)也postMessage不到頁(yè)面。那要如何才能在首次install就postMessage到頁(yè)面上那?答案是self.skipWaiting,然后在activate事件中使用self.clients.matchAll,因?yàn)檎{(diào)用了skipWaiting,當(dāng)前的sw在install以后會(huì)立刻avtivate并接管上一個(gè)sw的所有標(biāo)簽頁(yè),這樣就能在新sw中拿到標(biāo)簽頁(yè)postMessage了
self.skipWaiting() self.addEventListener("activate", () => { self.clients.matchAll() .then(function (clients) { clients.forEach(client => { client.postMessage("skipWaiting讓新的sw接管了頁(yè)面,這樣就可以收到"); }) }); })
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/108132.html
摘要:業(yè)界動(dòng)態(tài)發(fā)布版本,同時(shí)發(fā)布了版本以及首個(gè)穩(wěn)定版本的。程序人生如何用人類(lèi)的方式進(jìn)行二關(guān)于如何在中進(jìn)行良好的溝通,避免陷入一些潛在的陷阱。技術(shù)周刊由小組出品,匯聚一周好文章,周刊原文。 業(yè)界動(dòng)態(tài) Angular 5.1 & More Now Available Angular發(fā)布5.1版本,同時(shí)發(fā)布了Angular CLI 1.6版本以及首個(gè)穩(wěn)定版本的Angular Material。CL...
摘要:一閱前熱身為了更加形象的說(shuō)明同步異步阻塞非阻塞,我們以小明去買(mǎi)奶茶為例。等奶茶做好了,店員喊一聲小明,奶茶好了,然后小明去取奶茶。將響應(yīng)結(jié)果發(fā)給相應(yīng)的連接請(qǐng)求處理完成因?yàn)榛?,所以每個(gè)可以處理無(wú)數(shù)個(gè)連接請(qǐng)求。如此,就輕松的處理了高并發(fā)。 一、閱前熱身 為了更加形象的說(shuō)明同步異步、阻塞非阻塞,我們以小明去買(mǎi)奶茶為例。 1、同步與異步 ①同步與異步的理解 同步與異步的重點(diǎn)在消息通知的方式上...
摘要:一閱前熱身為了更加形象的說(shuō)明同步異步阻塞非阻塞,我們以小明去買(mǎi)奶茶為例。等奶茶做好了,店員喊一聲小明,奶茶好了,然后小明去取奶茶。將響應(yīng)結(jié)果發(fā)給相應(yīng)的連接請(qǐng)求處理完成因?yàn)榛?,所以每個(gè)可以處理無(wú)數(shù)個(gè)連接請(qǐng)求。如此,就輕松的處理了高并發(fā)。 一、閱前熱身 為了更加形象的說(shuō)明同步異步、阻塞非阻塞,我們以小明去買(mǎi)奶茶為例。 1、同步與異步 ①同步與異步的理解 同步與異步的重點(diǎn)在消息通知的方式上...
閱讀 3484·2021-11-19 09:40
閱讀 1502·2021-10-13 09:41
閱讀 2677·2021-09-29 09:35
閱讀 2723·2021-09-23 11:21
閱讀 1716·2021-09-09 11:56
閱讀 845·2019-08-30 15:53
閱讀 853·2019-08-30 15:52
閱讀 606·2019-08-30 12:47