Service Worker 概念简介
原文
豐富的離線體驗(yàn)、定期后臺(tái)同步、推送通知——通常需要原生應(yīng)用程序的功能——正在網(wǎng)絡(luò)上出現(xiàn)。 Service Worker 提供了所有這些功能所依賴的技術(shù)基礎(chǔ)。
What is a service worker
Service Worker 是瀏覽器在后臺(tái)運(yùn)行的腳本,與網(wǎng)頁分開,為不需要網(wǎng)頁或用戶交互的功能打開大門。 今天,它們已經(jīng)包含推送通知和后臺(tái)同步等功能。 將來,Service Worker 可能會(huì)支持其他功能,例如定期同步或地理圍欄。 本教程中討論的核心功能是攔截和處理網(wǎng)絡(luò)請(qǐng)求的能力,包括以編程方式管理響應(yīng)緩存。
這是一個(gè)如此令人興奮的 API 的原因是它允許您支持離線體驗(yàn),讓開發(fā)人員完全控制體驗(yàn)。
在 Service Worker 之前,還有一個(gè) API 可以為用戶提供網(wǎng)絡(luò)離線體驗(yàn),稱為 AppCache。 服務(wù)工作者旨在避免 AppCache API 的許多問題。
Service Worker 的注意事項(xiàng):
它是一個(gè) JavaScript Worker,所以它不能直接訪問 DOM。
相反,Service Worker 可以通過響應(yīng)通過 postMessage 接口發(fā)送的消息與其控制的頁面進(jìn)行通信,如果需要,這些頁面可以操作 DOM。
Service Worker 是一個(gè)可編程的網(wǎng)絡(luò)代理,允許您控制如何處理來自您的頁面的網(wǎng)絡(luò)請(qǐng)求。
它在不使用時(shí)終止,并在下一次需要時(shí)重新啟動(dòng),因此您不能依賴 Service Worker 的 onfetch 和 onmessage 處理程序中的全局狀態(tài)。 如果您需要在重啟后保留和重用某些信息,Service Worker 確實(shí)可以訪問 IndexedDB API。
The service worker life cycle
Service Worker 的生命周期與您的網(wǎng)頁完全分開。
要為您的站點(diǎn)安裝 Service Worker,您需要在頁面的 JavaScript 中注冊(cè)它。注冊(cè) Service Worker 將導(dǎo)致瀏覽器在后臺(tái)啟動(dòng) Service Worker 安裝步驟。
通常在安裝步驟中,您需要緩存一些靜態(tài)資產(chǎn)。如果所有文件都被成功緩存,那么 Service Worker 就會(huì)被安裝。如果任何文件無法下載和緩存,則安裝步驟將失敗并且 Service Worker 將不會(huì)激活(即不會(huì)被安裝)。如果發(fā)生這種情況,請(qǐng)不要擔(dān)心,它下次會(huì)再試一次。但這意味著如果它確實(shí)安裝了,您就知道緩存中已經(jīng)有了這些靜態(tài)資產(chǎn)。
安裝后,將執(zhí)行激活步驟,這是處理舊緩存管理的絕佳機(jī)會(huì),我們將在 Service Worker 更新部分進(jìn)行介紹。
在激活步驟之后,Service Worker 將控制其范圍內(nèi)的所有頁面,盡管第一次注冊(cè) Service Worker 的頁面在再次加載之前不會(huì)受到控制。一旦 Service Worker 處于控制狀態(tài),它將處于兩種狀態(tài)之一:Service Worker 將被終止以節(jié)省內(nèi)存,或者它會(huì)處理從您的頁面發(fā)出網(wǎng)絡(luò)請(qǐng)求或消息時(shí)發(fā)生的 fetch 和 message 事件。
下面是首次安裝時(shí) Service Worker 生命周期的過度簡(jiǎn)化版本。
Register a service worker
要安裝 Service Worker,您需要通過在您的頁面中注冊(cè)它來啟動(dòng)該過程。 這會(huì)告訴瀏覽器您的 Service Worker JavaScript 文件所在的位置。
if ('serviceWorker' in navigator) {window.addEventListener('load', function() {navigator.serviceWorker.register('/sw.js').then(function(registration) {// Registration was successfulconsole.log('ServiceWorker registration successful with scope: ', registration.scope);}, function(err) {// registration failed :(console.log('ServiceWorker registration failed: ', err);});}); }此代碼檢查 service worker API 是否可用,如果可用,則在頁面加載后注冊(cè) /sw.js 中的 service worker。
您可以在每次頁面加載時(shí)調(diào)用 register() 而不用擔(dān)心; 瀏覽器會(huì)判斷 service worker 是否已經(jīng)注冊(cè)并相應(yīng)地處理它。
register() 方法的一個(gè)微妙之處是 service worker 文件的位置。 在這種情況下,您會(huì)注意到 service worker 文件位于域的根目錄。 這意味著服務(wù)工作者的范圍將是整個(gè)源。
換句話說,這個(gè) Service Worker 將接收該域上所有內(nèi)容的 fetch 事件。 如果我們?cè)?/example/sw.js 注冊(cè) Service Worker 文件,那么 Service Worker 只會(huì)看到 URL 以 /example/ 開頭的頁面(即 /example/page1/、/example/page2/)的 fetch 事件。
現(xiàn)在,您可以通過轉(zhuǎn)到 chrome://inspect/#service-workers 并查找您的站點(diǎn)來檢查 Service Worker 是否已啟用。
您可能會(huì)發(fā)現(xiàn)在隱身窗口中測(cè)試您的 Service Worker 很有用,這樣您就可以關(guān)閉并重新打開,因?yàn)橹暗?Service Worker 不會(huì)影響新窗口。 一旦該窗口關(guān)閉,從隱身窗口中創(chuàng)建的任何注冊(cè)和緩存都將被清除。
Install a service worker
在受控頁面啟動(dòng)注冊(cè)過程后,讓我們轉(zhuǎn)向處理安裝事件的服務(wù)工作者腳本的觀點(diǎn)。
對(duì)于最基本的示例,您需要為安裝事件定義回調(diào)并決定要緩存哪些文件。
self.addEventListener('install', function(event) {// Perform install steps });在我們的安裝回調(diào)中,我們需要執(zhí)行以下步驟:
在這里你可以看到我們用我們想要的緩存名稱調(diào)用 caches.open() ,之后我們調(diào)用 cache.addAll() 并傳入我們的文件數(shù)組。 這是一個(gè)承諾鏈(caches.open() 和 cache.addAll())。 event.waitUntil() 方法接受一個(gè) promise 并使用它來知道安裝需要多長(zhǎng)時(shí)間,以及它是否成功。
如果所有文件都成功緩存,則將安裝 Service Worker。 如果任何文件下載失敗,則安裝步驟將失敗。 這允許您依賴您定義的所有資產(chǎn),但確實(shí)意味著您需要小心您決定在安裝步驟中緩存的文件列表。 定義一長(zhǎng)串文件會(huì)增加一個(gè)文件無法緩存的可能性,從而導(dǎo)致您的 Service Worker 無法安裝。
這只是一個(gè)示例,您可以在安裝事件中執(zhí)行其他任務(wù)或完全避免設(shè)置安裝事件偵聽器。
Cache and return requests
現(xiàn)在您已經(jīng)安裝了 Service Worker,您可能想要返回緩存的響應(yīng)之一,對(duì)嗎?
安裝 Service Worker 并且用戶導(dǎo)航到不同頁面或刷新后,Service Worker 將開始接收 fetch 事件,示例如下。
self.addEventListener('fetch', function(event) {event.respondWith(caches.match(event.request).then(function(response) {// Cache hit - return responseif (response) {return response;}return fetch(event.request);})); });這里我們定義了 fetch 事件,在 event.respondWith() 中,我們從 caches.match() 中傳入了一個(gè) promise。 此方法查看請(qǐng)求并從您的 Service Worker 創(chuàng)建的任何緩存中查找任何緩存結(jié)果。
如果我們有匹配的響應(yīng),我們返回緩存的值,否則我們返回調(diào)用 fetch 的結(jié)果,如果可以從網(wǎng)絡(luò)中檢索到任何東西,它將發(fā)出網(wǎng)絡(luò)請(qǐng)求并返回?cái)?shù)據(jù)。 這是一個(gè)簡(jiǎn)單的示例,使用我們?cè)诎惭b步驟中緩存的任何緩存資產(chǎn)。
如果我們想累積緩存新請(qǐng)求,我們可以通過處理 fetch 請(qǐng)求的響應(yīng)然后將其添加到緩存中來實(shí)現(xiàn),如下所示。
self.addEventListener('fetch', function(event) {event.respondWith(caches.match(event.request).then(function(response) {// Cache hit - return responseif (response) {return response;}return fetch(event.request).then(function(response) {// Check if we received a valid responseif(!response || response.status !== 200 || response.type !== 'basic') {return response;}// IMPORTANT: Clone the response. A response is a stream// and because we want the browser to consume the response// as well as the cache consuming the response, we need// to clone it so we have two streams.var responseToCache = response.clone();caches.open(CACHE_NAME).then(function(cache) {cache.put(event.request, responseToCache);});return response;});})); });更多Jerry的原創(chuàng)文章,盡在:“汪子熙”:
總結(jié)
以上是生活随笔為你收集整理的Service Worker 概念简介的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 双色球生肖幸运选号 大乐透生肖生日选号器
- 下一篇: SAP 产品一脉相承的 UI 增强思路,