放送中

漸進式網路應用程式的重要特點是可靠性,即使網路連線品質不佳,也能快速載入資產,讓使用者保持參與度並立即獲得回饋。這怎麼可能?這要歸功於 Service Worker fetch 事件。

擷取事件

Browser Support

  • Chrome: 40.
  • Edge: 17.
  • Firefox: 44.
  • Safari: 11.1.

Source

透過 fetch 事件,我們可以攔截 PWA 在 Service Worker 範圍內發出的每個網路要求,包括同源和跨來源要求。除了導覽和資產要求,從已安裝的 Service Worker 擷取資料,也能讓網站在首次載入後,無須發出網路呼叫即可算繪網頁瀏覽。

fetch 處理常式會接收應用程式的所有要求,包括網址和 HTTP 標頭,並讓應用程式開發人員決定如何處理這些要求。

服務工作人員位於用戶端和網路之間。

Service Worker 可以將要求轉送至網路、使用先前快取的回應來回應,或建立新的回應。一切由你決定。 簡單範例如下:

self.addEventListener("fetch", event => {     console.log(`URL requested: ${event.request.url}`); }); 

回覆要求

當服務工作人員收到要求時,您可以選擇忽略要求 (讓要求傳送至網路),也可以選擇回應要求。在 Service Worker 中回應要求,即可選擇要將哪些內容傳回 PWA,以及傳回方式,即使使用者處於離線狀態也沒問題。

如要回應傳入的要求,請在 fetch 事件處理常式中呼叫 event.respondWith(),如下所示:

// fetch event handler in your service worker file self.addEventListener("fetch", event => {     const response = .... // a response or a Promise of response     event.respondWith(response); }); 

您必須同步呼叫 respondWith(),並傳回 Response 物件。不過,您無法在擷取事件處理常式完成後呼叫 respondWith(),例如在非同步呼叫中。如需等待完整的回應,可以將 Promise 傳遞至 respondWith(),並以 Response 解析。

建立回覆

有了 Fetch API,您可以在 JavaScript 程式碼中建立 HTTP 回應,這些回覆可使用 Cache Storage API 進行快取,並以來自網頁伺服器的形式傳回。

如要建立回應,請建立新的 Response 物件,並設定其內文和選項,例如狀態和標頭:

const simpleResponse = new Response("Body of the HTTP response");  const options = {    status: 200,    headers: {     'Content-type': 'text/html'    } }; const htmlResponse = new Response("<b>HTML</b> content", options) 

從快取回應

您已瞭解如何從 Service Worker 提供 HTTP 回應,現在可以使用 Caching Storage 介面,將資產儲存在裝置上。

您可以使用快取儲存空間 API 檢查快取中是否有 PWA 傳送的要求,如果有的話,就以該要求回應 respondWith()。 如要這麼做,請先在快取中搜尋。頂層 caches 介面提供的 match() 函式會搜尋來源中的所有商店,或搜尋單一開啟的快取物件。

match() 函式會接收 HTTP 要求或網址做為引數,並傳回 Promise,該 Promise 會以與對應鍵相關聯的 Response 解決。

// Global search on all caches in the current origin caches.match(urlOrRequest).then(response => {    console.log(response ? response : "It's not in the cache"); });  // Cache-specific search caches.open("pwa-assets").then(cache => {   cache.match(urlOrRequest).then(response => {     console.log(response ? response : "It's not in the cache");   }); }); 

快取策略

只從瀏覽器快取提供檔案,並不適用於所有用途。舉例來說,使用者或瀏覽器可以清除快取。因此,您應自行定義策略,為 PWA 提供資產。您不限於使用一種快取策略。您可以為不同的網址模式定義不同的變數。舉例來說,您可以為最低 UI 資產制定一項策略,為 API 呼叫制定另一項策略,並為圖片和資料網址制定第三項策略。 如要這麼做,請在 ServiceWorkerGlobalScope.onfetch中讀取 event.request.url,並透過規則運算式或 URL 模式剖析。(撰寫本文時,並非所有平台都支援網址模式)。

最常見的策略包括:

快取優先
先搜尋快取的回應,如果找不到,則會改用網路。
電視網優先
先向網路要求回應,如果沒有傳回任何內容,則檢查快取中的回應。
網頁無回應時顯示過時內容
從快取提供回應,同時在背景要求最新版本,並儲存至快取,以供下次要求資產時使用。
僅限聯播網
一律會回覆網路的回應或錯誤。系統絕不會查詢快取。
僅限快取
一律會回覆快取中的回應或錯誤。系統絕不會諮詢該網路。使用這項策略放送的資產必須先加入快取,才能提出要求。

先快取

使用這項策略時,服務工作人員會在快取中尋找相符的要求,並在快取中找到對應的 Response 時傳回該 Response。否則會從網路擷取回應 (視需要更新快取,以供日後呼叫)。如果沒有快取回應或網路回應,要求就會發生錯誤。由於不需連上網路即可放送素材資源,速度通常較快,因此這項策略會優先考量成效,而非即時性。

「快取優先」策略

self.addEventListener("fetch", event => {    event.respondWith(      caches.match(event.request)      .then(cachedResponse => {        // It can update the cache to serve updated content on the next request          return cachedResponse || fetch(event.request);      }    )   ) }); 

網路優先

這項策略與「快取優先」策略相反,會檢查是否可透過網路滿足要求,如果無法,則嘗試從快取擷取要求。例如「先快取」。如果沒有網路回應或快取回應,要求就會發生錯誤。從網路取得回應通常比從快取取得回應慢,因此這項策略會優先處理更新內容,而非效能。

「網路優先」策略

self.addEventListener("fetch", event => {    event.respondWith(      fetch(event.request)      .catch(error => {        return caches.match(event.request) ;      })    ); }); 

網頁無回應時顯示過時內容

「過時後重新驗證」策略會立即傳回快取的回應,然後檢查網路是否有更新,並在找到更新時取代快取的回應。這項策略一律會發出網路要求,因為即使找到快取資源,系統也會嘗試使用從網路收到的內容更新快取中的內容,以便在下一個要求中使用更新後的版本。因此,這項策略可讓您享有快取優先策略的快速服務,並在背景更新快取。

「過時後重新驗證」策略

self.addEventListener('fetch', event => {   event.respondWith(     caches.match(event.request).then(cachedResponse => {         const networkFetch = fetch(event.request).then(response => {           // update the cache with a clone of the network response           const responseClone = response.clone()           caches.open(url.searchParams.get('name')).then(cache => {             cache.put(event.request, responseClone)           })           return response         }).catch(function (reason) {           console.error('ServiceWorker fetch failed: ', reason)         })         // prioritize cached response over network         return cachedResponse || networkFetch       }     )   ) }) 

僅限網路

「僅限網路」策略與瀏覽器在沒有 Service Worker 或 Cache Storage API 時的行為類似。只有在可從網路擷取資源時,要求才會傳回資源。這通常適用於僅限線上的 API 要求等資源。

僅限聯播網策略

僅限快取

「僅限快取」策略可確保要求絕不會傳送至網路,所有傳入的要求都會以預先填入的快取項目回應。下列程式碼會搭配快取儲存空間的 match 方法使用 fetch 事件處理常式,只回應快取:

self.addEventListener("fetch", event => {    event.respondWith(caches.match(event.request)); }); 

僅快取策略。

自訂策略

雖然上述是常見的快取策略,但您仍須負責服務工作人員和要求的處理方式。如果這些都不符合需求,請自行建立。

舉例來說,您可以搭配逾時使用「網路優先」策略,優先處理更新內容,但前提是回應必須在您設定的門檻內出現。您也可以將快取回應與網路回應合併,並從 Service Worker 建構複雜的回應。

更新資產

讓 PWA 的快取資產保持在最新狀態可能很困難。雖然「過時重新驗證」策略是其中一種做法,但並非唯一方法。在更新章節中,您將學到各種技巧,確保應用程式的內容和資產保持在最新狀態。

資源