Cache
注意:此功能在 Web Workers 中可用。
Cache 介面提供了一種持久化儲存機制,用於儲存 Request / Response 物件對,這些物件被快取在長壽命記憶體中。Cache 物件的生命週期取決於瀏覽器,但單個源的指令碼通常可以依賴於先前填充的 Cache 物件。請注意,Cache 介面既暴露給視窗作用域,也暴露給 worker。您不必將其與 service worker 結合使用,即使它是在 service worker 規範中定義的。
一個源可以有多個命名 Cache 物件。您負責實現指令碼(例如,在 ServiceWorker 中)如何處理 Cache 更新。Cache 中的專案不會自動更新,除非明確請求;它們不會過期,除非被刪除。使用 CacheStorage.open() 來開啟特定的命名 Cache 物件,然後呼叫任何 Cache 方法來維護 Cache。
您還負責定期清理快取條目。每個瀏覽器對給定源可以使用的快取儲存量都有硬性限制。可以透過 StorageManager.estimate() 方法估算 Cache 配額使用情況。瀏覽器會盡最大努力管理磁碟空間,但它可能會刪除源的 Cache 儲存。瀏覽器通常會刪除一個源的所有資料,或者不刪除任何資料。請確保透過名稱對快取進行版本化,並僅使用可以安全操作它們的指令碼版本中的快取。有關更多資訊,請參閱 刪除舊快取。
注意: 鍵匹配演算法取決於值的 VARY 頭。因此,匹配新鍵需要檢視 Cache 物件中條目的鍵和值。
注意: 快取 API 不遵守 HTTP 快取頭。
例項方法
Cache.match()-
返回一個
Promise,該 Promise 解析為Cache物件中第一個匹配請求的響應。 Cache.matchAll()-
返回一個
Promise,該 Promise 解析為Cache物件中所有匹配響應的陣列。 Cache.add()-
接收一個 URL,檢索它,並將結果響應物件新增到給定的快取中。這在功能上等同於呼叫
fetch(),然後使用put()將結果新增到快取。 Cache.addAll()-
接收一個 URL 陣列,檢索它們,並將結果響應物件新增到給定的快取中。
Cache.put()-
接收請求及其響應,並將它們新增到給定的快取中。
Cache.delete()-
查詢鍵為請求的
Cache條目,返回一個Promise,如果找到並刪除了匹配的Cache條目,則該 Promise 解析為true。如果未找到Cache條目,則 Promise 解析為false。 Cache.keys()-
返回一個
Promise,該 Promise 解析為Cache鍵的陣列。
示例
此程式碼片段來自 service worker 選擇性快取示例。(請參閱 選擇性快取即時演示) 程式碼使用 CacheStorage.open() 來開啟任何 Content-Type 頭以 font/ 開頭的 Cache 物件。
然後,程式碼使用 Cache.match() 來檢查快取中是否已有匹配的字型,如果有,則返回它。如果不存在匹配的字型,程式碼將從網路獲取字型,並使用 Cache.put() 將獲取的資源快取起來。
程式碼處理從 fetch() 操作丟擲的異常。請注意,HTTP 錯誤響應(例如 404)不會引發異常。它將返回一個具有相應錯誤程式碼的正常響應物件。
程式碼片段還展示了 service worker 使用的快取版本化的最佳實踐。雖然在此示例中只有一個快取,但相同的方法可用於多個快取。它將快取的簡短識別符號對映到特定的、版本化的快取名稱。程式碼還會刪除所有未在 CURRENT_CACHES 中命名的快取。
在程式碼示例中,caches 是 ServiceWorkerGlobalScope 的一個屬性。它包含 CacheStorage 物件,透過它可以訪問 CacheStorage 介面。
注意: 在 Chrome 中,訪問 chrome://inspect/#service-workers 並點選已註冊的 service worker 下方的“inspect”連結,可以檢視 service-worker.js 指令碼執行的各種操作的日誌記錄語句。
const CACHE_VERSION = 1;
const CURRENT_CACHES = {
font: `font-cache-v${CACHE_VERSION}`,
};
self.addEventListener("activate", (event) => {
// Delete all caches that aren't named in CURRENT_CACHES.
// While there is only one cache in this example, the same logic
// will handle the case where there are multiple versioned caches.
const expectedCacheNamesSet = new Set(Object.values(CURRENT_CACHES));
event.waitUntil(
caches.keys().then((cacheNames) =>
Promise.all(
cacheNames.map((cacheName) => {
if (!expectedCacheNamesSet.has(cacheName)) {
// If this cache name isn't present in the set of
// "expected" cache names, then delete it.
console.log("Deleting out of date cache:", cacheName);
return caches.delete(cacheName);
}
return undefined;
}),
),
),
);
});
self.addEventListener("fetch", (event) => {
console.log("Handling fetch event for", event.request.url);
event.respondWith(
caches
.open(CURRENT_CACHES.font)
.then((cache) => cache.match(event.request))
.then((response) => {
if (response) {
// If there is an entry in the cache for event.request,
// then response will be defined and we can just return it.
// Note that in this example, only font resources are cached.
console.log(" Found response in cache:", response);
return response;
}
// Otherwise, if there is no entry in the cache for event.request,
// response will be undefined, and we need to fetch() the resource.
console.log(
" No response for %s found in cache. About to fetch " +
"from network…",
event.request.url,
);
// We call .clone() on the request since we might use it
// in a call to cache.put() later on.
// Both fetch() and cache.put() "consume" the request,
// so we need to make a copy.
// (see https://mdn.club.tw/en-US/docs/Web/API/Request/clone)
return fetch(event.request.clone()).then((response) => {
console.log(
" Response for %s from network is: %O",
event.request.url,
response,
);
if (
response.status < 400 &&
response.headers.has("content-type") &&
response.headers.get("content-type").match(/^font\//i)
) {
// This avoids caching responses that we know are errors
// (i.e. HTTP status code of 4xx or 5xx).
// We also only want to cache responses that correspond
// to fonts, i.e. have a Content-Type response header that
// starts with "font/".
// Note that for opaque filtered responses
// https://fetch.spec.whatwg.org/#concept-filtered-response-opaque
// we can't access to the response headers, so this check will
// always fail and the font won't be cached.
// All of the Google Web Fonts are served from a domain that
// supports CORS, so that isn't an issue here.
// It is something to keep in mind if you're attempting
// to cache other resources from a cross-origin
// domain that doesn't support CORS, though!
console.log(" Caching the response to", event.request.url);
// We call .clone() on the response to save a copy of it
// to the cache. By doing so, we get to keep the original
// response object which we will return back to the controlled
// page.
// https://mdn.club.tw/en-US/docs/Web/API/Request/clone
cache.put(event.request, response.clone());
} else {
console.log(" Not caching the response to", event.request.url);
}
// Return the original response object, which will be used to
// fulfill the resource request.
return response;
});
})
.catch((error) => {
// This catch() will handle exceptions that arise from the match()
// or fetch() operations.
// Note that a HTTP error response (e.g. 404) will NOT trigger
// an exception.
// It will return a normal response object that has the appropriate
// error code set.
console.error(" Error in fetch handler:", error);
throw error;
}),
);
});
Cookie 和 Cache 物件
Fetch API 要求在從 fetch() 返回 Response 物件之前,刪除 Set-Cookie 頭。因此,儲存在 Cache 中的 Response 將不包含 Set-Cookie 頭,因此不會導致任何 Cookie 被儲存。
規範
| 規範 |
|---|
| Service Workers # cache-interface |
瀏覽器相容性
載入中…