快取儲存空間是一項強大的工具,這樣一來,應用程式就不會那麼依賴網路狀況。善用快取可讓網路應用程式離線運作,並在任何網路狀況下盡快提供資產。如「資產和資料」一文所述,您可以決定快取必要資產的最佳策略。如要管理服務工作人員互動的快取,請使用 Cache Storage API。
Cache Storage API 可從不同環境取得:
- 視窗環境 (PWA 的主執行緒)。
- Service Worker。
- 您使用的任何其他工作人員。
使用 Service Worker 管理快取的優點之一,是其生命週期不會與視窗綁定,因此不會封鎖主執行緒。請注意,如要使用 Cache Storage API,大多數情境都必須採用 TLS 連線。
要快取的內容
您可能會先想到要快取哪些內容。雖然這個問題沒有單一答案,但您可以先從算繪使用者介面所需的所有最低資源開始。
這些資源應包括:
- 主要網頁 HTML (應用程式的 start_url)。
- 主要使用者介面所需的 CSS 樣式表。
- 使用者介面中使用的圖片。
- 用於算繪使用者介面的必要 JavaScript 檔案。
- 用於呈現基本體驗的資料,例如 JSON 檔案。
- 網頁字型。
- 在多頁面應用程式中,您要快速或離線提供的其他 HTML 文件。
可離線使用
雖然離線功能是漸進式網頁應用程式的必要條件之一,但請務必瞭解,並非所有 PWA 都需要完整的離線體驗,例如雲端遊戲解決方案或加密資產應用程式。因此,您可以提供基本使用者介面,引導使用者處理這些情況。
PWA 不應顯示瀏覽器的錯誤訊息,指出網頁轉譯引擎無法載入網頁。請改用服務工作人員顯示自己的訊息,避免出現一般且令人困惑的瀏覽器錯誤。
視 PWA 的需求而定,您可以使用許多不同的快取策略。因此,請務必設計快取使用方式,提供快速且穩定的體驗。舉例來說,如果所有應用程式資產都能快速下載、不會佔用大量空間,且不需要在每次要求時更新,那麼快取所有資產就是有效的策略。另一方面,如果資源必須是最新版本,您可能完全不想快取這些資產。
使用 API
使用 Cache Storage API 在來源中定義一組快取,每個快取都以您定義的字串名稱識別。透過 caches
物件存取 API,並使用 open
方法建立快取,或開啟已建立的快取。open 方法會傳回快取物件的 Promise。
caches.open("pwa-assets")
.then(cache => {
// you can download and store, delete or update resources with cache arguments
});
下載及儲存資產
如要要求瀏覽器下載及儲存資產,請使用 add
或 addAll
方法。add
方法會發出要求並儲存一個 HTTP 回應,而 addAll
則會根據要求或網址陣列,將一組 HTTP 回應儲存為交易。
caches.open("pwa-assets")
.then(cache => {
cache.add("styles.css"); // it stores only one resource
cache.addAll(["styles.css", "app.js"]); // it stores two resources
});
快取儲存介面會儲存整個回應,包括所有標頭和內文。因此,您稍後可以使用 HTTP 要求或網址做為鍵來擷取該值。具體做法請見「提供服務」章節。
快取時機
在 PWA 中,您可以決定何時要快取檔案。其中一種做法是在安裝 Service Worker 時盡可能儲存大量資產,但通常不是最佳做法。快取不必要的資源會浪費頻寬和儲存空間,且可能導致應用程式提供非預期的過時資源。
您不需要一次快取所有資產,可以在 PWA 的生命週期內多次快取資產,例如:
- 在安裝 Service Worker 時。
- 首次載入網頁後。
- 使用者前往某個區段或路徑時。
- 網路處於閒置狀態時。
您可以在主執行緒或 Service Worker 環境中,要求快取新檔案。
在 Service Worker 中快取資產
最常見的情況之一,是在安裝 Service Worker 時,快取最少量的資產。如要這麼做,您可以在 Service Worker 的 install
事件中使用快取儲存空間介面。
由於服務工作人員執行緒隨時可能停止,您可以要求瀏覽器等待 addAll
Promise 完成,提高儲存所有資產的機會,並確保應用程式一致性。以下範例說明如何使用服務工作人員事件監聽器中收到的事件引數 waitUntil
方法,執行這項操作。
const urlsToCache = ["/", "app.js", "styles.css", "logo.svg"];
self.addEventListener("install", event => {
event.waitUntil(
caches.open("pwa-assets")
.then(cache => {
return cache.addAll(urlsToCache);
});
);
});
waitUntil()
方法會接收 Promise,並要求瀏覽器等待 Promise 中的工作解析 (已完成或失敗),再終止 Service Worker 程序。您可能需要串連 Promise,並傳回 add()
或 addAll()
呼叫,讓單一結果傳送至 waitUntil()
方法。
您也可以使用 async/await 語法處理 Promise。在這種情況下,您需要建立可呼叫 await
的非同步函式,並在呼叫後將 Promise 傳回至 waitUntil()
,如下列範例所示:
const urlsToCache = ["/", "app.js", "styles.css", "logo.svg"];
self.addEventListener("install", (event) => {
let cacheUrls = async () => {
const cache = await caches.open("pwa-assets");
return cache.addAll(urlsToCache);
};
event.waitUntil(cacheUrls());
});
跨網域要求和不透明回應
PWA 可以從來源和跨網域下載及快取資產,例如第三方 CDN 的內容。如果是跨網域應用程式,快取互動方式與同源要求非常相似。系統會執行要求,並將回應副本儲存在快取中。與其他快取資產一樣,這項資產只能在應用程式來源中使用。
資產會儲存為不透明的回應,也就是說,您的程式碼無法查看或修改該回應的內容或標頭。此外,不透明的回應不會在 Storage API 中顯示實際大小,因此會影響配額。部分瀏覽器會顯示較大的大小,例如 7 MB,即使檔案只有 1 KB 也是如此。
更新及刪除資產
您可以使用 cache.put(request, response)
更新資產,並使用 delete(request)
刪除資產。
詳情請參閱 Cache 物件說明文件。
偵錯快取儲存空間
許多瀏覽器都提供方法,讓您在開發人員工具的「應用程式」分頁中,偵錯快取儲存空間的內容。您可以在這裡查看目前來源中每個快取的內容。我們會在「工具和偵錯」一章中,進一步說明這些工具。