摘要:需要提前掌握的基本使用檢測(cè)是否存在,創(chuàng)建緩存總對(duì)象。之后更新后的啟動(dòng)并觸發(fā)事件。此時(shí),當(dāng)前頁(yè)面生效的依然是老版本的,新的會(huì)進(jìn)入狀態(tài)。當(dāng)頁(yè)面關(guān)閉之后,老的會(huì)被干掉,新的接管頁(yè)面一旦新的生效后會(huì)觸發(fā)事件。
前言: 看到一篇講解service worker的文章, 基礎(chǔ)講的還不錯(cuò), 所以轉(zhuǎn)了以后作為自己的參考
Service Worker是什么service worker 是獨(dú)立于當(dāng)前頁(yè)面的一段運(yùn)行在瀏覽器后臺(tái)進(jìn)程里的腳本。它的特性將包括推送消息,背景后臺(tái)同步, geofencing(地理圍欄定位),攔截和處理網(wǎng)絡(luò)請(qǐng)求。
這個(gè) API 會(huì)讓人興奮的原因是,它可以使你的應(yīng)用先訪問本地緩存資源,所以在離線狀態(tài)時(shí),在沒有通過網(wǎng)絡(luò)接收到更多的數(shù)據(jù)前,仍可以提供基本的功能(一般稱之為 Offline First)。
在 service worker 之前,另一個(gè)叫做 APP Cache 的 api 也可以提供離線體驗(yàn)。APP Cache 的的主要問題是坑比較多,而且其被設(shè)計(jì)為只適合于單頁(yè) web 應(yīng)用程序,對(duì)于傳統(tǒng)的多頁(yè)網(wǎng)站則不適合。service worker 的設(shè)計(jì)規(guī)避了這些痛點(diǎn)。
關(guān)于 service worker 的一些注意點(diǎn):
service worker 是一個(gè)JavaScript worker ,所以它不能直接訪問 DOM 。但 service worker 可以通過postMessage 接口與跟其相關(guān)的頁(yè)面進(jìn)行通信,發(fā)送消息,從而讓這些頁(yè)面在有需要的時(shí)候去操縱 DOM 。
Service worker 是一個(gè)可編程的網(wǎng)絡(luò)代理,允許你去控制如何處理頁(yè)面的網(wǎng)絡(luò)請(qǐng)求, 可以處理fetch請(qǐng)求。
Service worker 在不使用時(shí)將被終止,并會(huì)在需要的時(shí)候重新啟動(dòng),因此你不能把onfetch 和onmessage事件來(lái)作為全局依賴處理程序。如果你需要持久話一些信息并在重新啟動(dòng)Service worker后使用他,可以使用 IndexedDBAPI ,service worker 支持。
Service Worker 的緩存機(jī)制是依賴 Cache API 實(shí)現(xiàn)的 Service worker 廣泛使用了 promise。
Service worker依賴 HTML5 fetch API
Service Workers 要求必須在 HTTPS 下才能運(yùn)行
Service Worker生命周期注冊(cè)service worker,在網(wǎng)頁(yè)上生效
安裝成功,激活 或者 安裝失敗(下次加載會(huì)嘗試重新安裝)
激活后,在sw的作用域下作用所有的頁(yè)面,首次控制sw不會(huì)生效,下次加載頁(yè)面才會(huì)生效。
sw作用頁(yè)面后,處理fetch(網(wǎng)絡(luò)請(qǐng)求)和message(頁(yè)面消息)事件 或者 被終止(節(jié)省內(nèi)存)。
需要提前掌握的APICache API基本使用
(1)檢測(cè)api是否存在
if("caches" in window) { // Has support! }
(2)caches.open,創(chuàng)建緩存總對(duì)象。如下創(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只添加一個(gè),cache.addAll可以添加多個(gè)。
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對(duì)象包含以下屬性:
method - GET, POST, PUT, DELETE, HEAD
url - 請(qǐng)求的鏈接
headers - 請(qǐng)求的header對(duì)象
referrer - 請(qǐng)求的referrer對(duì)象
mode - cors, no-cors, same-origin
credentials - 設(shè)置請(qǐng)求可不可以攜帶cookie
redirect - follow, error, manual
integrity - 子資源完整值
cache - 緩存模式 (default, reload, no-cache)
可以在fetch中傳入Request對(duì)象實(shí)例:
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對(duì)象實(shí)例,其中的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對(duì)象
另外Response的實(shí)例還具備以下方法:
clone() - 創(chuàng)建Response對(duì)象的克隆。
error() - 返回與網(wǎng)絡(luò)錯(cuò)誤關(guān)聯(lián)的新Response對(duì)象。
redirect() - 使用不同的URL創(chuàng)建新響應(yīng)。
arrayBuffer() - 返回使用ArrayBuffer解析的promise。
blob() - 返回使用Blob解析的promise。
formData() - 返回使用FormData對(duì)象解析的promise。
json() - 返回使用JSON對(duì)象解析的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的一個(gè)polyfill,Service Worker需要依賴Cache API:
self.importScripts("./serviceworker-cache-polyfill.js");
注冊(cè)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 這個(gè)文件將會(huì)作為 service worker 被注冊(cè)。
如果這個(gè) service worker 已經(jīng)被注冊(cè)過,瀏覽器會(huì)自動(dòng)忽略上面的代碼。
有一個(gè)特別要注意是 service worker 文件的路徑。你一定注意到,在這個(gè)例子中,service worker 文件被放在這個(gè)域的根目錄下,這意味著 service worker是跟網(wǎng)站同源的。換句話說,這個(gè) service worker 將會(huì)獲取到這個(gè)域下的所有 fetch 事件。如果 service worker文件注冊(cè)到/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 就安裝成功了。如果任何一個(gè)文件下載失敗,那么安裝步驟就會(huì)失敗。這個(gè)方式依賴于你自己指定的資源,但這意味著,你需要非常仔細(xì)地確定哪些文件需要被緩存。指定了太多文件的話,會(huì)增加失敗率。
對(duì)緩存跟返回請(qǐng)求的處理
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; } ); }) );
如果我們想在緩存中添加新的請(qǐng)求緩存,可以通過處理fetch請(qǐng)求的response,將其添加到緩存中即可。代碼里我們做了以下事情:
添加一個(gè) callback 到 fetch 請(qǐng)求的 .then 方法中。 一旦我們獲得一個(gè) response,我們進(jìn)行如下的檢查:
1. 確保 response 有效
2. 檢查 response 的狀態(tài)是200
3. 確保 response 的類型是 basic 類型的,這說明請(qǐng)求是同源的,這意味著第三方的請(qǐng)求不能被緩存。
如果檢查通過會(huì)clone 這個(gè)請(qǐng)求。這么做的原因是如果 response 是一個(gè) Stream,那么它的 body 只能被消費(fèi)一次。所以為了讓瀏覽器跟緩存都使用這個(gè)body,我們必須克隆這個(gè) body,一份到瀏覽器,一份到緩存中緩存。
重新激活你的 service worker 總會(huì)有要更新的時(shí)候。在那時(shí),你需要按照以下步驟來(lái)更新:
更新你 service worker 的 JavaScript 文件 當(dāng)用戶瀏覽你的網(wǎng)站時(shí),瀏覽器嘗試在后臺(tái)重新下載 service worker 的腳本文件。經(jīng)過對(duì)比,只要服務(wù)器上的文件和本地文件有一個(gè)字節(jié)不同,這個(gè)文件就認(rèn)為是新的。
之后更新后的 service worker 啟動(dòng)并觸發(fā) install 事件。此時(shí),當(dāng)前頁(yè)面生效的依然是老版本的 service worker,新的 service worker 會(huì)進(jìn)入 “waiting” 狀態(tài)。
當(dāng)頁(yè)面關(guān)閉之后,老的 service worker 會(huì)被干掉,新的 servicer worker 接管頁(yè)面 一旦新的 service worker 生效后會(huì)觸發(fā) activate 事件。 通常來(lái)講,需要在 activate 的 callback 中進(jìn)行 cache 管理,來(lái)清理老的 cache。我們?cè)?activate 而不是 install 的時(shí)候進(jìn)行的原因,是如果我們?cè)?install 的時(shí)候進(jìn)行清理,那么老的 service worker 仍然在控制頁(yè)面,他們依賴的緩存就失效了,因此就會(huì)突然被停止。
之前我們使用的緩存可以叫 my-site-cache-v1 ,我們想把這個(gè)拆封到多個(gè)緩存,一份給頁(yè)面使用,一份給博客文章使用。這意味著,install 步驟里,我們要?jiǎng)?chuàng)建兩個(gè)緩存: pages-cache-v1 和 blog-posts-cache-v1。在 activite 步驟里,我們需要?jiǎng)h除舊的 my-site-cache-v1。
下面的代碼會(huì)遍歷所有的緩存,并刪除掉不在 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)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/104194.html
摘要:是瀏覽器和服務(wù)器之間的腳本,主要作用是攔截請(qǐng)求,修改響應(yīng),以及一些其他的作用。這是出于安全因素的考慮。這個(gè)注冊(cè)的過程是發(fā)生在之外的。在安裝完成,激活之前,它不會(huì)攔截任何請(qǐng)求。將會(huì)始終攔截請(qǐng)求,重啟頁(yè)面也是為了這個(gè)。 pwa-之service worker 基本概念pwa-之service worker 離線文件處理 學(xué)習(xí)service worker 基本概念 在本章,將涵蓋以下內(nèi)容 ...
摘要:是瀏覽器和服務(wù)器之間的腳本,主要作用是攔截請(qǐng)求,修改響應(yīng),以及一些其他的作用。這是出于安全因素的考慮。這個(gè)注冊(cè)的過程是發(fā)生在之外的。在安裝完成,激活之前,它不會(huì)攔截任何請(qǐng)求。將會(huì)始終攔截請(qǐng)求,重啟頁(yè)面也是為了這個(gè)。 pwa-之service worker 基本概念pwa-之service worker 離線文件處理 學(xué)習(xí)service worker 基本概念 在本章,將涵蓋以下內(nèi)容 ...
摘要:需要提前掌握的基本使用檢測(cè)是否存在,創(chuàng)建緩存總對(duì)象。之后更新后的啟動(dòng)并觸發(fā)事件。此時(shí),當(dāng)前頁(yè)面生效的依然是老版本的,新的會(huì)進(jìn)入狀態(tài)。當(dāng)頁(yè)面關(guān)閉之后,老的會(huì)被干掉,新的接管頁(yè)面一旦新的生效后會(huì)觸發(fā)事件。 前言: 看到一篇講解service worker的文章, 基礎(chǔ)講的還不錯(cuò), 所以轉(zhuǎn)了以后作為自己的參考 Service Worker是什么 service worker 是獨(dú)立于當(dāng)前頁(yè)面...
摘要:當(dāng)下比較火,而是實(shí)現(xiàn)的一項(xiàng)關(guān)鍵技術(shù),今天我們一起了解下關(guān)于的一些基礎(chǔ)知識(shí)和適用場(chǎng)景。資源查找順序?yàn)閺淖笙蛴遥业劫Y源則返回,未找到則繼續(xù)尋找,直至最終獲取資源。借助,真正讓應(yīng)用變得流行,也許就在不久的將來(lái)。 當(dāng)下PWA比較火,而Service Worker是實(shí)現(xiàn)PWA的一項(xiàng)關(guān)鍵技術(shù),今天我們一起了解下關(guān)于Service Worker的一些基礎(chǔ)知識(shí)和適用場(chǎng)景。 什么是Server Wor...
摘要:的生命周期的生命周期與頁(yè)面完全分離。換句話說,這個(gè)將為這個(gè)域中的所有內(nèi)容接收事件。這不是必要的,但絕對(duì)是推薦的。新的將啟動(dòng)并且安裝事件將被移除。使用,可以很容易被劫持連接并偽造響應(yīng)。后臺(tái)同步允許延遲操作,直到用戶具有穩(wěn)定的連接。 這是專門探索 JavaScript 及其所構(gòu)建的組件的系列文章的第8篇。 想閱讀更多優(yōu)質(zhì)文章請(qǐng)猛戳GitHub博客,一年百來(lái)篇優(yōu)質(zhì)文章等著你! 如果你錯(cuò)過了前...
閱讀 2753·2021-11-22 14:45
閱讀 896·2021-10-15 09:41
閱讀 1058·2021-09-27 13:35
閱讀 3662·2021-09-09 11:56
閱讀 2626·2019-08-30 13:03
閱讀 3191·2019-08-29 16:32
閱讀 3296·2019-08-26 13:49
閱讀 766·2019-08-26 10:35