Signatur
Beschreibung
Die Eigenschaft caches ist in jedem Worker-Kontext verfügbar, also in Service Workern, Dedicated Workern und Shared Workern. Sie gibt das CacheStorage-Objekt zurück, das dem Ursprung (Origin) des Workers zugeordnet ist. Im Worker schreibt man sie meist ohne Präfix als globales caches oder als self.caches.
Über CacheStorage öffnet, durchsucht und löscht man benannte Caches (caches.open(), caches.match(), caches.keys(), caches.delete()). Jeder Cache speichert Paare aus Request und Response. So lassen sich Offline-Fähigkeit, Precaching beim install-Event und Strategien wie „Cache zuerst“ oder „Netzwerk zuerst“ im fetch-Handler eines Service Workers umsetzen.
Der Speicher ist derselbe wie bei window.caches im Hauptthread desselben Ursprungs. Daten, die ein Service Worker ablegt, kann die Seite also direkt lesen, und umgekehrt. Alle Methoden arbeiten asynchron und liefern Promises. Deshalb eignet sich die API gut für async/await.
Rückgabewert
CacheStorage-Objekt des aktuellen Ursprungs. Die Eigenschaft ist schreibgeschützt.Beispiele
Precaching beim install-Event eines Service Workers
// sw.js
const CACHE_NAME = 'app-v1';
const ASSETS = ['/', '/index.html', '/styles.css', '/app.js'];
self.addEventListener('install', (event) => {
event.waitUntil(
(async () => {
const cache = await caches.open(CACHE_NAME);
await cache.addAll(ASSETS);
console.log('Assets vorab gecacht:', ASSETS.length);
})()
);
});
Strategie „Cache zuerst, sonst Netzwerk“ im fetch-Handler
self.addEventListener('fetch', (event) => {
if (event.request.method !== 'GET') return;
event.respondWith(
(async () => {
const cached = await caches.match(event.request);
if (cached) return cached;
const response = await fetch(event.request);
// Nur erfolgreiche, eigene Antworten zwischenspeichern
if (response.ok && response.type === 'basic') {
const cache = await caches.open('runtime-v1');
await cache.put(event.request, response.clone());
}
return response;
})()
);
});
Veraltete Caches beim activate-Event aufräumen
const AKTUELL = ['app-v2', 'runtime-v1'];
self.addEventListener('activate', (event) => {
event.waitUntil(
(async () => {
const namen = await caches.keys();
const alt = namen.filter((name) => !AKTUELL.includes(name));
await Promise.all(alt.map((name) => caches.delete(name)));
console.log('Gelöscht:', alt);
})()
);
});
Nutzung in einem Dedicated Worker
// worker.js
self.addEventListener('message', async ({ data }) => {
if (!('caches' in self)) {
self.postMessage({ fehler: 'CacheStorage nicht verfügbar' });
return;
}
const cache = await caches.open('daten-v1');
let res = await cache.match(data.url);
if (!res) {
res = await fetch(data.url);
await cache.put(data.url, res.clone());
}
self.postMessage(await res.json());
});
// Wichtig · Fallstricke
- Nur in sicheren Kontexten: Die Eigenschaft gibt es nur unter HTTPS oder
localhost. Unter HTTP istcachesundefined. Deshalb vor der Nutzung mit'caches' in selfprüfen. - Response nur einmal lesbar: Der Körper einer
Responselässt sich nur einmal auslesen. Wer eine Antwort zurückgibt und zugleich cachen will, muss sie mitresponse.clone()kopieren. - Keine automatische Ablaufzeit: Die Cache-API beachtet keine HTTP-Caching-Header. Einträge bleiben erhalten, bis man sie selbst löscht. Caches deshalb versionieren und im
activate-Event aufräumen. - Speicherkontingent: Der Browser kann den Speicher bei Platzmangel räumen. Mit
navigator.storage.persist()lässt sich dauerhafter Speicher anfordern, undnavigator.storage.estimate()zeigt den Verbrauch. cache.put()lehnt Nicht-GET-Anfragen ab. Opake Antworten (type: 'opaque') haben den Status 0 und belegen viel vom Kontingent.- Im privaten Modus mancher Browser (z. B. Firefox) kann
cachesfehlen oder Fehler werfen.