Service Worker Caching
Während Service Worker und PWAs zu Standards moderner Webanwendungen werden, ist das Ressourcen-Caching komplexer als je zuvor. In diesem Beitrag werden die wichtigsten Aspekte des Browser-Cachings behandelt.
Während Service Worker und PWAs zu Standards moderner Webanwendungen werden, ist das Ressourcen-Caching komplexer als je zuvor. In diesem Beitrag werden die wichtigsten Aspekte des Browser-Cachings behandelt.
Analog zum Browser-Cache ist die Strategie, zuerst im eigenen Cache nach der gefragten Ressource zu suchen, für die meisten Anwendungsfälle passend. Bauen wir also auf dieses Szenario auf und vervollständigen die Kaskade.
Wenn die Ressource noch nicht im Cache ist, gibt es zwei Möglichkeiten: A, wir haben eine Netzwerkverbindung zum Server oder B, wir sind offline. Trifft letzteres zu, also B, zeigen wir eine Offline-Seite an. Wie du einen Service Worker installierst und eine Offline-Seite bereitstellst, findest du hier.
Im Normalfall trifft jedoch A zu und wir fragen den Server nach der Ressource. Dazu gibt es wiederum zwei Möglichkeiten, auf die wir näher eingehen sollten.
Bis der Service Worker geladen, installiert und aktiviert ist, können bis zu fünfzig Millisekunden verstreichen. Aus Performance-Gründen wartet der Browser daher mit seiner ersten Anfrage nicht auf den Service Worker. Wir sollten aber beim Aktivieren des Service Workers die Antwort auf diese Erstanfrage berücksichtigen, indem wir die Unterstützung dieses Preloads einschalten.
// Call Activate Event
self.addEventListener('activate', event => {
console.log('Service Worker: Activated');
event.waitUntil(
(async () => {
// enable navigation preload
await self.registration.navigationPreload.enable();
// remove unwanted caches
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cache => {
if (cache !== cacheName) return caches.delete(cache);
})
);
});
})()
);
// tell the active service worker to take control of the page immediately
self.clients.claim();
});
Jetzt können wir diesen Preload abfangen, eine Kopie davon in den Cache legen und dann die Ressource zur Anzeige geben.
Diese Erstanfrage und folgedessen auch die Anwort enthält aber nicht alles, sondern nur die Navigation, also die initiale Seite ohne beispielsweise Bilder, die darin geladen werden. Alles weitere müssen wir also noch erfragen. Und falls der Browser gar keine Erstanfrage gesendet hat, müssen wir alles erfragen. Auch hier fangen wir die Antwort ab und erstellen eine Kopie für den Cache, bevor wir sie zur Anzeige weitergeben.
// Call Fetch Event
self.addEventListener('fetch', event => {
const requestURL = new URL(event.request.url);
if ((requestURL.origin == location.origin) && (event.request.method != 'POST')) {
event.respondWith(
caches.open(cacheName)
.then((cache) => {
return cache.match(event.request)
.then((cachedResponse) => {
// frist try to return the page from cache
if (cachedResponse) {
return cachedResponse;
}
// if we are offline display the offline page
if (!navigator.onLine) {
return caches.match(offlineUrl);
}
// then try to return the preload and add the cache
if ((event.request.mode === 'navigate') && event.preloadResponse) {
return Promise.resolve(event.preloadResponse)
.then((preloadResponse) => {
cache.put(event.request, preloadResponse.clone());
return preloadResponse;
})
}
// finaly try the network and add the cache
return fetch(event.request)
.then((networkResponse) => {
cache.put(event.request, networkResponse.clone());
return networkResponse;
})
})
.catch(() => {
// if all fails display the offline page again
return caches.match(offlineUrl);
})
})
);
}
});
Das sieht nun zumindest vorderhand alles gut aus.
Wenn du deine Website aktualisierst, wirst du feststellen, dass weiterhin der alte Inhalt aus dem Cache geladen wird, maixmal für die nächsten neunzig Tage. So lange bleibt standardmässig der Cache gültig.
Das reicht dir nicht? Dann ist es Zeit für eine Cache-Update-Strategie.
Du hast es geschafft.
Die gesamte service-worker.js kannst du direkt herunterladen, falls du keine Lust hast, die obigen Code-Schnipsel zusammenzusetzen. Dort ist dann auch gleich die Push-Notification enthalten.
Falls du an weiteren News und Anleitungen von mir interessiert bist, abonniere meine Web-Push-Benachrichtigungen.