摘要:需要提前掌握的基本使用檢測是否存在,創(chuàng)建緩存總對象。之后更新后的啟動并觸發(fā)事件。此時,當(dāng)前頁面生效的依然是老版本的,新的會進入狀態(tài)。當(dāng)頁面關(guān)閉之后,老的會被干掉,新的接管頁面一旦新的生效后會觸發(fā)事件。
前言: 看到一篇講解service worker的文章, 基礎(chǔ)講的還不錯, 所以轉(zhuǎn)了以后作為自己的參考
Service Worker是什么service worker 是獨立于當(dāng)前頁面的一段運行在瀏覽器后臺進程里的腳本。它的特性將包括推送消息,背景后臺同步, geofencing(地理圍欄定位),攔截和處理網(wǎng)絡(luò)請求。
這個 API 會讓人興奮的原因是,它可以使你的應(yīng)用先訪問本地緩存資源,所以在離線狀態(tài)時,在沒有通過網(wǎng)絡(luò)接收到更多的數(shù)據(jù)前,仍可以提供基本的功能(一般稱之為 Offline First)。
在 service worker 之前,另一個叫做 APP Cache 的 api 也可以提供離線體驗。APP Cache 的的主要問題是坑比較多,而且其被設(shè)計為只適合于單頁 web 應(yīng)用程序,對于傳統(tǒng)的多頁網(wǎng)站則不適合。service worker 的設(shè)計規(guī)避了這些痛點。
關(guān)于 service worker 的一些注意點:
service worker 是一個JavaScript worker ,所以它不能直接訪問 DOM 。但 service worker 可以通過postMessage 接口與跟其相關(guān)的頁面進行通信,發(fā)送消息,從而讓這些頁面在有需要的時候去操縱 DOM 。
Service worker 是一個可編程的網(wǎng)絡(luò)代理,允許你去控制如何處理頁面的網(wǎng)絡(luò)請求, 可以處理fetch請求。
Service worker 在不使用時將被終止,并會在需要的時候重新啟動,因此你不能把onfetch 和onmessage事件來作為全局依賴處理程序。如果你需要持久話一些信息并在重新啟動Service worker后使用他,可以使用 IndexedDBAPI ,service worker 支持。
Service Worker 的緩存機制是依賴 Cache API 實現(xiàn)的 Service worker 廣泛使用了 promise。
Service worker依賴 HTML5 fetch API
Service Workers 要求必須在 HTTPS 下才能運行
Service Worker生命周期注冊service worker,在網(wǎng)頁上生效
安裝成功,激活 或者 安裝失敗(下次加載會嘗試重新安裝)
激活后,在sw的作用域下作用所有的頁面,首次控制sw不會生效,下次加載頁面才會生效。
sw作用頁面后,處理fetch(網(wǎng)絡(luò)請求)和message(頁面消息)事件 或者 被終止(節(jié)省內(nèi)存)。
需要提前掌握的APICache API基本使用
(1)檢測api是否存在
if("caches" in window) { // Has support! }
(2)caches.open,創(chuàng)建緩存總對象。如下創(chuàng)建名為 test-cache 的緩存。
caches.open("test-cache").then(function(cache) { // Cache is created and accessible });
(3)cache.add和cache.addAll,添加緩存內(nèi)容。其中cache.add只添加一個,cache.addAll可以添加多個。
caches.open("test-cache").then(function(cache) { cache.addAll(["/", "/images/logo.png"]) .then(function() { // Cached! // or use cache.add cache.add("/page/1"); // "/page/1" URL will be fetched and cached! }); });
(4)cache.keys(),查看已經(jīng)緩存的數(shù)據(jù)
caches.open("test-cache").then(function(cache) { cache.keys().then(function(cachedRequests) { console.log(cachedRequests); // [Request, Request] }); });
(5)cache.match和cache.matchAll,匹配緩存文件路徑
caches.open("test-cache").then(function(cache) { cache.match("/page/1").then(function(matchedResponse) { console.log(matchedResponse); }); });
(6)cache.delete,刪除緩存。
caches.open("test-cache").then(function(cache) { cache.delete("/page/1"); });
Fetch API基本使用
// url (required), options (optional) fetch("https://davidwalsh.name/some/url", { method: "get" }).then(function(response) { }).catch(function(err) { // Error :( });
其中options對象包含以下屬性:
method - GET, POST, PUT, DELETE, HEAD
url - 請求的鏈接
headers - 請求的header對象
referrer - 請求的referrer對象
mode - cors, no-cors, same-origin
credentials - 設(shè)置請求可不可以攜帶cookie
redirect - follow, error, manual
integrity - 子資源完整值
cache - 緩存模式 (default, reload, no-cache)
可以在fetch中傳入Request對象實例:
var request = new Request("https://davidwalsh.name/users.json", { method: "POST", mode: "cors", redirect: "follow", headers: new Headers({ "Content-Type": "text/plain" }) }); // Now use it! fetch(request).then(function() { /* handle response */ });
可以自定義返回的Response對象實例,其中的options有:
type - basic, cors
url
useFinalURL - 上面的url參數(shù)是不是最終的URL
status - 狀態(tài)碼(ex: 200, 404, etc.)
ok - 是否成功響應(yīng) (范圍在 200-299)
statusText - 狀態(tài)碼 (ex: OK)
headers - 響應(yīng)的headers對象
另外Response的實例還具備以下方法:
clone() - 創(chuàng)建Response對象的克隆。
error() - 返回與網(wǎng)絡(luò)錯誤關(guān)聯(lián)的新Response對象。
redirect() - 使用不同的URL創(chuàng)建新響應(yīng)。
arrayBuffer() - 返回使用ArrayBuffer解析的promise。
blob() - 返回使用Blob解析的promise。
formData() - 返回使用FormData對象解析的promise。
json() - 返回使用JSON對象解析的promise。
text() - 返回使用USVString(文本)解析的promise。
// Create your own response for service worker testing // new Response(BODY, OPTIONS) var response = new Response(".....", { ok: false, status: 404, url: "/" }); // The fetch"s `then` gets a Response instance back fetch("https://davidwalsh.name/") .then(function(responseObj) { console.log("status: ", responseObj.status); });Service Worker的使用
兼容低版本,注入Cache API的一個polyfill,Service Worker需要依賴Cache API:
self.importScripts("./serviceworker-cache-polyfill.js");
注冊service worker:
if ("serviceWorker" in navigator) { navigator.serviceWorker.register("/sw.js").then(function(registration) { // Registration was successful console.log("ServiceWorker registration successful with scope: ", registration.scope); }).catch(function(err) { // registration failed :( console.log("ServiceWorker registration failed: ", err); }); }
上面的代碼檢查 service worker API 是否可用,如果可用, /sw.js 這個文件將會作為 service worker 被注冊。
如果這個 service worker 已經(jīng)被注冊過,瀏覽器會自動忽略上面的代碼。
有一個特別要注意是 service worker 文件的路徑。你一定注意到,在這個例子中,service worker 文件被放在這個域的根目錄下,這意味著 service worker是跟網(wǎng)站同源的。換句話說,這個 service worker 將會獲取到這個域下的所有 fetch 事件。如果 service worker文件注冊到/example/sw.js ,那么 service worker 只能收到 /example/ 路徑下的 fetch 事件(比如: /example/page1/, /example/page2/)。
安裝service worker:
var CACHE_NAME = "my-site-cache-v1"; var urlsToCache = [ "/", "/styles/main.css", "/script/main.js" ]; self.addEventListener("install", function(event) { // Perform install steps event.waitUntil( caches.open(CACHE_NAME) .then(function(cache) { console.log("Opened cache"); return cache.addAll(urlsToCache); }) ); });
上面代碼聲明了需要緩存的內(nèi)容,如果所有的文件都緩存成功,service worker 就安裝成功了。如果任何一個文件下載失敗,那么安裝步驟就會失敗。這個方式依賴于你自己指定的資源,但這意味著,你需要非常仔細(xì)地確定哪些文件需要被緩存。指定了太多文件的話,會增加失敗率。
對緩存跟返回請求的處理
self.addEventListener("fetch", function(event) { event.respondWith( caches.match(event.request) .then(function(response) { // Cache hit - return response if (response) { return response; } // IMPORTANT: Clone the request. A request is a stream and // can only be consumed once. Since we are consuming this // once by cache and once by the browser for fetch, we need // to clone the response var fetchRequest = event.request.clone(); return fetch(fetchRequest).then( function(response) { // Check if we received a valid response if(!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 2 stream. var responseToCache = response.clone(); caches.open(CACHE_NAME) .then(function(cache) { cache.put(event.request, responseToCache); }); return response; } ); }) );
如果我們想在緩存中添加新的請求緩存,可以通過處理fetch請求的response,將其添加到緩存中即可。代碼里我們做了以下事情:
添加一個 callback 到 fetch 請求的 .then 方法中。 一旦我們獲得一個 response,我們進行如下的檢查:
1. 確保 response 有效
2. 檢查 response 的狀態(tài)是200
3. 確保 response 的類型是 basic 類型的,這說明請求是同源的,這意味著第三方的請求不能被緩存。
如果檢查通過會clone 這個請求。這么做的原因是如果 response 是一個 Stream,那么它的 body 只能被消費一次。所以為了讓瀏覽器跟緩存都使用這個body,我們必須克隆這個 body,一份到瀏覽器,一份到緩存中緩存。
重新激活你的 service worker 總會有要更新的時候。在那時,你需要按照以下步驟來更新:
更新你 service worker 的 JavaScript 文件 當(dāng)用戶瀏覽你的網(wǎng)站時,瀏覽器嘗試在后臺重新下載 service worker 的腳本文件。經(jīng)過對比,只要服務(wù)器上的文件和本地文件有一個字節(jié)不同,這個文件就認(rèn)為是新的。
之后更新后的 service worker 啟動并觸發(fā) install 事件。此時,當(dāng)前頁面生效的依然是老版本的 service worker,新的 service worker 會進入 “waiting” 狀態(tài)。
當(dāng)頁面關(guān)閉之后,老的 service worker 會被干掉,新的 servicer worker 接管頁面 一旦新的 service worker 生效后會觸發(fā) activate 事件。 通常來講,需要在 activate 的 callback 中進行 cache 管理,來清理老的 cache。我們在 activate 而不是 install 的時候進行的原因,是如果我們在 install 的時候進行清理,那么老的 service worker 仍然在控制頁面,他們依賴的緩存就失效了,因此就會突然被停止。
之前我們使用的緩存可以叫 my-site-cache-v1 ,我們想把這個拆封到多個緩存,一份給頁面使用,一份給博客文章使用。這意味著,install 步驟里,我們要創(chuàng)建兩個緩存: pages-cache-v1 和 blog-posts-cache-v1。在 activite 步驟里,我們需要刪除舊的 my-site-cache-v1。
下面的代碼會遍歷所有的緩存,并刪除掉不在 cacheWhitelist 數(shù)組(我們定義的緩存白名單)中的緩存。
self.addEventListener("activate", function(event) { var cacheWhitelist = ["pages-cache-v1", "blog-posts-cache-v1"]; event.waitUntil( caches.keys().then(function(cacheNames) { return Promise.all( cacheNames.map(function(cacheName) { if (cacheWhitelist.indexOf(cacheName) === -1) { return caches.delete(cacheName); } }) ); }) ); });
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/62107.html
摘要:是瀏覽器和服務(wù)器之間的腳本,主要作用是攔截請求,修改響應(yīng),以及一些其他的作用。這是出于安全因素的考慮。這個注冊的過程是發(fā)生在之外的。在安裝完成,激活之前,它不會攔截任何請求。將會始終攔截請求,重啟頁面也是為了這個。 pwa-之service worker 基本概念pwa-之service worker 離線文件處理 學(xué)習(xí)service worker 基本概念 在本章,將涵蓋以下內(nèi)容 ...
摘要:是瀏覽器和服務(wù)器之間的腳本,主要作用是攔截請求,修改響應(yīng),以及一些其他的作用。這是出于安全因素的考慮。這個注冊的過程是發(fā)生在之外的。在安裝完成,激活之前,它不會攔截任何請求。將會始終攔截請求,重啟頁面也是為了這個。 pwa-之service worker 基本概念pwa-之service worker 離線文件處理 學(xué)習(xí)service worker 基本概念 在本章,將涵蓋以下內(nèi)容 ...
摘要:需要提前掌握的基本使用檢測是否存在,創(chuàng)建緩存總對象。之后更新后的啟動并觸發(fā)事件。此時,當(dāng)前頁面生效的依然是老版本的,新的會進入狀態(tài)。當(dāng)頁面關(guān)閉之后,老的會被干掉,新的接管頁面一旦新的生效后會觸發(fā)事件。 前言: 看到一篇講解service worker的文章, 基礎(chǔ)講的還不錯, 所以轉(zhuǎn)了以后作為自己的參考 Service Worker是什么 service worker 是獨立于當(dāng)前頁面...
摘要:當(dāng)下比較火,而是實現(xiàn)的一項關(guān)鍵技術(shù),今天我們一起了解下關(guān)于的一些基礎(chǔ)知識和適用場景。資源查找順序為從左向右,找到資源則返回,未找到則繼續(xù)尋找,直至最終獲取資源。借助,真正讓應(yīng)用變得流行,也許就在不久的將來。 當(dāng)下PWA比較火,而Service Worker是實現(xiàn)PWA的一項關(guān)鍵技術(shù),今天我們一起了解下關(guān)于Service Worker的一些基礎(chǔ)知識和適用場景。 什么是Server Wor...
摘要:的生命周期的生命周期與頁面完全分離。換句話說,這個將為這個域中的所有內(nèi)容接收事件。這不是必要的,但絕對是推薦的。新的將啟動并且安裝事件將被移除。使用,可以很容易被劫持連接并偽造響應(yīng)。后臺同步允許延遲操作,直到用戶具有穩(wěn)定的連接。 這是專門探索 JavaScript 及其所構(gòu)建的組件的系列文章的第8篇。 想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你! 如果你錯過了前...
閱讀 2585·2021-11-23 09:51
閱讀 3129·2019-08-30 15:54
閱讀 1083·2019-08-30 14:14
閱讀 3557·2019-08-30 13:59
閱讀 1416·2019-08-29 17:09
閱讀 1475·2019-08-29 16:24
閱讀 2861·2019-08-29 15:43
閱讀 921·2019-08-29 12:45