隨著前端快速發(fā)展,應(yīng)用的性能已經(jīng)變得至關(guān)重要,關(guān)于這一點大佬做了很多統(tǒng)計。你可以去看看。
如何降低一個頁面的網(wǎng)絡(luò)請求成本從而縮短頁面加載資源的時間并降低用戶可感知的延時是非常重要的一部分。對于提升應(yīng)用的加載速度常用的手段有Http Cache、異步加載、304緩存、文件壓縮、CDN、CSS Sprite、開啟GZIP等等。這些手段無非是在做一件事情,就是讓資源更快速的下載到瀏覽器端。但是除了這些方法,其實還有更加強大的Service Worker線程。
Service Worker與PWA的現(xiàn)狀
說起service worker就不得不提起PWA了,service worker做為PWA的核心技術(shù)之一,多年來一直被Google大力推廣,這里簡單介紹一下。
通俗來說,PWA就是漸進式web應(yīng)用(Progressive Web App)。早在16年初,Google便提出PWA,希望提供更強大的web體驗,引導(dǎo)開發(fā)者回歸開放互聯(lián)網(wǎng)。它彌補了web對比Native App急缺的幾個能力,比如離線使用、后臺加載、添加到主屏和消息推送等,同時它還具備了小程序標榜的“無需安裝、用完即走”的特性。
雖然PWA技術(shù)已經(jīng)被W3C列為標準,但是其落地情況一直以來是很讓人失望的,始終受到蘋果的阻礙,最重要的原因在于PWA繞過Apple Store審核,直接推給用戶。如果普及,這將威脅到蘋果的平臺權(quán)威,也就意味著蘋果與開發(fā)者的三七分成生意將會落空。
所以一直以來safrai不支持mainfest以及service worker這兩項關(guān)鍵技術(shù),即使在18年開始支持了,但是對PWA的支持力度也遠遠低于安卓,具體體現(xiàn)在service worker緩存無法永久保存,以及service worker的API支持不夠完善,一個最明顯的不同在于安卓版本的PWA會保留你的登錄狀態(tài),并且會系統(tǒng)級推送消息。而在蘋果上,這兩點都做不到。也就是說,iPhone上的微博PWA,每次打開都要重新登錄,而且不會收到任何推送信息。
另外由于某些不可描述的原因,在國內(nèi)無法使用Service Worker的推送功能,雖然國內(nèi)已經(jīng)有兩家公司做了service worker的瀏覽器推送,但是成熟度還有待調(diào)研。
由于目前各版本手機瀏覽器對service worker的支持度都不太相同,同一個接口也存在差異化還有待統(tǒng)一,之于我們來說,也只能用Service Worker做一做PC瀏覽器的緩存了。
Service Worker的由來
Service Worker(以下簡稱sw)是基于WEB Worker而來的。
眾所周知,javaScript 是單線程的,隨著web業(yè)務(wù)的復(fù)雜化,開發(fā)者逐漸在js中做了許多耗費資源的運算過程,這使得單線程的弊端更加凹顯。web worker正是基于此被創(chuàng)造出來,它是脫離在主線程之外的,我們可以將復(fù)雜耗費時間的事情交給web worker來做。但是web worker作為一個獨立的線程,他的功能應(yīng)當不僅于此。sw便是在web worker的基礎(chǔ)上增加了離線緩存的能力。當然在 Service Worker 之前也有在 HTML5 上做離線緩存的 API 叫 AppCache, 但是 AppCache 存在很多缺點,你可以親自看看。
sw是由事件驅(qū)動的,具有生命周期,可以攔截處理頁面的所有網(wǎng)絡(luò)請求(fetch),可以訪問cache和indexDB,支持推送,并且可以讓開發(fā)者自己控制管理緩存的內(nèi)容以及版本,為離線弱網(wǎng)環(huán)境下的 web 的運行提供了可能,讓 web 在體驗上更加貼近 native。換句話說他可以把你應(yīng)用里的所有靜態(tài)動態(tài)資源根據(jù)不同策略緩存起來,在你下次打開時不再需要去服務(wù)器請求,這樣一來就減少了網(wǎng)絡(luò)耗時,使得web應(yīng)用可以秒開,并且在離線環(huán)境下也變得可用。做到這一切你只需要增加一個sw文件,不會對原有的代碼產(chǎn)生任何侵入,是不是很perfect?
Service Worker基本特征
無法操作DOM
只能使用HTTPS以及l(fā)ocalhost
可以攔截全站請求從而控制你的應(yīng)用
與主線程獨立不會被阻塞(不要再應(yīng)用加載時注冊sw)
完全異步,無法使用XHR和localStorage
一旦被 install,就永遠存在,除非被 uninstall或者dev模式手動刪除
獨立上下文
響應(yīng)推送
后臺同步
。。。
service worker是事件驅(qū)動的worker,生命周期與頁面無關(guān)。 關(guān)聯(lián)頁面未關(guān)閉時,它也可以退出,沒有關(guān)聯(lián)頁面時,它也可以啟動。
Dedicated Worker以及Shared Worker與Service Worker三者非常重要的區(qū)別在于不同的生命周期。對于Service Worker來說文檔無關(guān)的生命周期,是它能提供可靠Web服務(wù)的一個重要基礎(chǔ)。
Service Worker生命周期
register 這個是由 client 端發(fā)起,注冊一個 serviceWorker,這需要一個專門處理sw邏輯的文件
Parsed 注冊完成,解析成功,尚未安裝
installing 注冊中,此時 sw 中會觸發(fā) install 事件, 需知 sw 中都是事件觸發(fā)的方式進行的邏輯調(diào)用,如果事件里有 event.waitUntil() 則會等待傳入的 Promise 完成才會成功
installed(waiting) 注冊完成,但是頁面被舊的 Service Worker 腳本控制, 所以當前的腳本尚未激活處于等待中,可以通過 self.skipWaiting() 跳過等待。
activating 安裝后要等待激活,也就是 activated 事件,只要 register 成功后就會觸發(fā) install ,但不會立即觸發(fā) activated,如果事件里有 event.waitUntil() 則會等待這個 Promise 完成才會成功,這時可以調(diào)用 Clients.claim() 接管所有頁面。
activated 在 activated 之后就可以開始對 client 的請求進行攔截處理,sw 發(fā)起請求用的是 fetch api,XHR無法使用
fetch 激活以后開始對網(wǎng)頁中發(fā)起的請求進行攔截處理
terminate 這一步是瀏覽器自身的判斷處理,當 sw 長時間不用之后,處于閑置狀態(tài),瀏覽器會把該 sw 暫停,直到再次使用
update 瀏覽器會自動檢測 sw 文件的更新,當有更新時會下載并 install,但頁面中還是老的 sw 在控制,只有當用戶新開窗口后新的 sw 才能激活控制頁面
redundant 安裝失敗, 或者激活失敗, 或者被新的 Service Worker 替代掉
Service Worker 腳本最常用的功能是截獲請求和緩存資源文件, 這些行為可以綁定在下面這些事件上:
install 事件中, 抓取資源進行緩存
activate 事件中, 遍歷緩存, 清除過期的資源
fetch 事件中, 攔截請求, 查詢緩存或者網(wǎng)絡(luò), 返回請求的資源