Signatur
Beschreibung
Mit open() greifst du über den Namen auf einen einzelnen Cache innerhalb des CacheStorage zu. Normalerweise erreichst du den CacheStorage über die globale Eigenschaft caches, und zwar sowohl im Fenster (window.caches) als auch in Workern und Service Workern (self.caches). Gibt es noch keinen Cache mit diesem Namen, legt der Browser automatisch einen neuen, leeren Cache an. open() gibt also nie undefined zurück.
Die Methode ist die Grundlage für Offline-Strategien in Service Workern. Beim install-Event öffnest du einen versionierten Cache (z. B. "app-shell-v3") und lädst mit cache.addAll() alle wichtigen Dateien vorab. Später kannst du beim fetch-Event mit cache.match() nach gespeicherten Antworten suchen oder neue Antworten mit cache.put() ablegen.
Der Cache-Name ist ein beliebiger String und gilt nur für den jeweiligen Origin. Hänge eine Version an den Namen an. Dann kannst du im activate-Event veraltete Caches gezielt mit caches.delete() entfernen. Für die Einträge in den Caches gibt es kein automatisches Ablaufdatum. Sie bleiben erhalten, bis du sie selbst löschst oder der Browser wegen Speicherdruck den Speicher des Origins leert.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $cacheName Pflicht | string | Name des Caches, der geöffnet werden soll. Gibt es ihn noch nicht, wird er angelegt. Andere Werte werden in einen String umgewandelt. |
Rückgabewert
Cache-Objekt zum angegebenen Namen erfüllt wird. Es wird z. B. mit einer SecurityError-DOMException abgelehnt, wenn der Speicherzugriff nicht erlaubt ist (unsicherer Kontext, blockierter Speicher).Beispiele
App-Shell beim Installieren des Service Workers vorab laden
// sw.js
const CACHE_NAME = 'app-shell-v3';
const ASSETS = ['/', '/index.html', '/styles.css', '/app.js', '/offline.html'];
self.addEventListener('install', (event) => {
event.waitUntil(
(async () => {
const cache = await caches.open(CACHE_NAME);
await cache.addAll(ASSETS);
console.log(`${ASSETS.length} Dateien in ${CACHE_NAME} gespeichert`);
})()
);
});
Cache-first-Strategie mit Rückgriff auf das Netzwerk
// sw.js
self.addEventListener('fetch', (event) => {
if (event.request.method !== 'GET') return;
event.respondWith((async () => {
const cache = await caches.open('runtime-v1');
const cached = await cache.match(event.request);
if (cached) return cached;
const response = await fetch(event.request);
// Nur erfolgreiche Antworten speichern; clone(), weil ein Body nur einmal lesbar ist
if (response.ok) {
await cache.put(event.request, response.clone());
}
return response;
})());
});
Alte Cache-Versionen beim Aktivieren entfernen
// sw.js
const CURRENT = ['app-shell-v3', 'runtime-v1'];
self.addEventListener('activate', (event) => {
event.waitUntil((async () => {
const names = await caches.keys();
const stale = names.filter((name) => !CURRENT.includes(name));
await Promise.all(stale.map((name) => caches.delete(name)));
console.log('Gelöscht:', stale);
})());
});
Aus dem Fenster heraus auf den Cache zugreifen
// Im normalen Seitenkontext (HTTPS)
const showCachedUrls = async () => {
if (!('caches' in window)) {
console.log('Cache API nicht verfügbar');
return;
}
const cache = await caches.open('app-shell-v3');
const requests = await cache.keys();
console.log(requests.map((req) => new URL(req.url).pathname));
};
showCachedUrls();
// Wichtig · Fallstricke
- Legt still einen Cache an: Bei einem Tippfehler im Namen bekommst du keinen Fehler, sondern einen neuen, leeren Cache. Willst du nur prüfen, ob ein Cache existiert, verwende
caches.has(name). - Nur sichere Kontexte:
cachesgibt es nur unter HTTPS oderlocalhost. In manchen Browsern ist es im privaten Modus oder bei blockierten Cookies bzw. blockiertem Speicher nicht verfügbar. Dann wird das Promise abgelehnt, odercachesistundefined. Prüfe deshalb vorher mit'caches' in self. - Kein automatisches Ablaufen: HTTP-Header wie
Cache-Controlwerden ignoriert. Veraltete Einträge und Caches musst du selbst entfernen, sonst wächst der Speicherverbrauch immer weiter. Mitnavigator.storage.estimate()kannst du den Verbrauch prüfen. - Speicher kann gelöscht werden: Bei Speicherdruck darf der Browser den ganzen Speicher eines Origins leeren. Safari löscht Daten von Websites, die länger nicht besucht wurden. Mit
navigator.storage.persist()kannst du um dauerhaften Speicher bitten. - Den Service Worker am Leben halten: Setze
open()iminstall- oderactivate-Event immer innerhalb vonevent.waitUntil()ein. Sonst kann der Worker beendet werden, bevor das Promise fertig ist. - Der Cache gilt nur für den eigenen Origin. Andere Origins können nicht auf ihn zugreifen.