Service Worker · API
Cache API
发布于
Cache API 是一个按源隔离、持久保存 Request/Response 对的存储,在 service worker 与页面中都通过 caches 全局对象(一个 CacheStorage)访问。除了你的代码写入或删除、以及存储压力下整源被驱逐之外,里面的内容不会变化。它自 Chrome 43、Edge 16、Firefox 41、Safari 11.1 起可用,且仅限安全上下文(BCD api.CacheStorage)。
// caches 全局对象const cache = await caches.open(cacheName);const hit = await caches.match(request, options);const exists = await caches.has(cacheName);const names = await caches.keys();const removed = await caches.delete(cacheName);
// Cacheawait cache.add(request);await cache.addAll([request1, request2]);await cache.put(request, response);const response = await cache.match(request, options);const responses = await cache.matchAll(request, options);const requests = await cache.keys(request, options);const deleted = await cache.delete(request, options);所有方法都返回 Promise。request 参数可以是 Request,也可以是 URL 字符串,后者会相对于 worker 或页面的地址解析。caches.open() 在缓存不存在时会创建它。
CacheStorage 管理带名字的缓存;Cache 保存其中一个缓存的条目。
| 成员 | 返回值 | 行为 |
|---|---|---|
caches.open(name) |
Promise<Cache> |
打开或创建指定名字的缓存。名字是任意字符串,这正是版本化命名(shell-v3)得以成立的原因。 |
caches.match(request, options) |
Promise<Response | undefined> |
按创建顺序搜索该源的所有缓存,以第一个命中兑现。options.cacheName 可把搜索限定在一个缓存内。 |
caches.has(name)、caches.keys()、caches.delete(name) |
Promise<boolean>、Promise<string[]>、Promise<boolean> |
对整个缓存做盘点与删除。名字不存在时 delete() 兑现为 false。 |
cache.add(request) |
Promise<void> |
发起请求并存储响应,相当于 fetch() 加 put()。 |
cache.addAll(requests) |
Promise<void> |
发起全部请求并原子性地存储:任一失败则一条都不存。 |
cache.put(request, response) |
Promise<void> |
存储你手头已有的响应,不发请求。body 流会被消耗,若还要把响应返回出去,先 clone()。 |
cache.match(request, options) |
Promise<Response | undefined> |
在本缓存中查找一个条目。 |
cache.matchAll(request, options) |
Promise<Response[]> |
匹配该请求的全部条目;省略 request 时返回所有条目。 |
cache.keys(request, options) |
Promise<Request[]> |
已存储的 Request 对象,便于按 URL 清理。 |
cache.delete(request, options) |
Promise<boolean> |
删除匹配的条目;至少删掉一条时兑现为 true。 |
options 是 CacheQueryOptions 字典:ignoreSearch 比较时忽略查询串,ignoreMethod 允许非 GET 请求匹配已存的 GET 条目,ignoreVary 跳过 Vary 头的匹配。条目以 URL 与方法为键,并且默认遵守已存响应的 Vary 头,所以 Accept-Language 不同的请求可能查不到一条在 DevTools 里明明存在的条目。
拒绝原因是 DOMException 或 TypeError。
TypeError:请求方法不是GET(add、addAll、put),请求 scheme 不是http:或https:,响应状态为206,或其Vary头含*。Chromium 的报错包括Partial response (status code 206) is unsupported与Vary header contains *。add()与addAll()的TypeError:某个响应不是ok(状态不在 200 到 299 之间)或请求失败。Chromium 报Request failed,因此预缓存列表里一个 404 就会让整个addAll()中止;若它运行在install的waitUntil()里,安装也随之失败。QuotaExceededError:put()、add()、addAll()写入时该源的存储配额已耗尽。Chromium 在配额核算中把每条 opaque(no-cors、状态0)响应按约 7 MB 计入,所以在接近满盘的设备上,几条第三方资源就可能触发它。SecurityError:在非安全上下文访问caches。在localhost以外的http:源上,window.caches为undefined,worker 中的self.caches也不可用。
下面两个示例分别是版本化缓存模式的 install 与 activate 两半,之后是一个针对 caches 缺失环境的检测示例。
在 install 中原子性地预缓存应用壳
Section titled “在 install 中原子性地预缓存应用壳”在 event.waitUntil() 内使用 addAll(),这样任何一个资源失败都会把有问题的 worker 挡在 active 槽位之外。
const SHELL = 'shell-v3';const ASSETS = ['/', '/app.js', '/app.css', '/offline.html'];
self.addEventListener('install', (event) => { event.waitUntil( caches.open(SHELL).then((cache) => cache.addAll(ASSETS)) );});由于 addAll() 是原子的,shell-v3 要么完整要么不存在;/app.css 返回 404 会让 Promise 被拒绝、安装失败,而原来处于 active 状态的 worker 继续服务。
在 activate 中删除被取代的缓存
Section titled “在 activate 中删除被取代的缓存”旧缓存不会自动清理。新 worker 激活后,删除所有不等于当前名字的缓存。
self.addEventListener('activate', (event) => { event.waitUntil( caches.keys().then((names) => Promise.all(names.filter((n) => n !== SHELL).map((n) => caches.delete(n))) ) );});这段代码要放在 activate 而不是 install 里:install 期间旧 worker 可能仍在用你要删除的那个缓存为页面提供服务。
检测支持,并在不支持时只在线运行
Section titled “检测支持,并在不支持时只在线运行”非安全源与没有该 API 的浏览器中没有 caches。下面的回退跳过 service worker 注册,并告知应用不要宣称支持离线。
export function initOffline() { if ('caches' in window && 'serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js'); return { offline: true }; } // 没有 Cache Storage:只在线运行,并隐藏"可离线使用"标记。 return { offline: false };}直接调用 caches.open() 的页面也应同样防护;在 http: 源上直接调用会在任何 Promise 产生之前就抛出。
- Service Workers specification: Cache interface(w3c.github.io)
- View Cache data in Chrome DevTools(developer.chrome.com)
- CacheStorage(developer.mozilla.org)
- Service worker 缓存策略
- FetchEvent 与请求路由
- Cache Storage
- 存储持久化、配额与驱逐
规范
| 规范 | 状态 |
|---|---|
| 无。 | |