Signatur
Beschreibung
FetchEvent.preloadResponse ist eine schreibgeschützte Eigenschaft des FetchEvent im Service Worker. Sie liefert ein Promise, das mit der Response des Navigation Preload erfüllt wird. Wenn für die Anfrage kein Preload gestartet wurde, wird das Promise mit undefined erfüllt. Das passiert zum Beispiel, wenn Navigation Preload ausgeschaltet ist, wenn es sich nicht um eine Navigationsanfrage handelt oder wenn der Browser die Funktion nicht unterstützt.
Ohne Navigation Preload wartet der Browser bei einer Seitennavigation erst, bis der Service Worker gestartet ist. Erst danach kann der Worker den Netzwerk-Request absetzen. Ist Navigation Preload über registration.navigationPreload.enable() eingeschaltet, startet der Browser den Request für die Navigation parallel zum Hochfahren des Service Workers. Im fetch-Handler greift man dann über event.preloadResponse auf diese bereits laufende Antwort zu und verhindert so einen doppelten Request.
Typischerweise wird Navigation Preload im activate-Event eingeschaltet. Im fetch-Handler gilt dann: Zuerst den Cache prüfen, dann die Preload-Antwort nutzen und erst zuletzt auf fetch(event.request) zurückfallen. Preload-Anfragen senden standardmäßig den Header Service-Worker-Navigation-Preload: true. Den Wert kann man mit navigationPreload.setHeaderValue() ändern, damit der Server zum Beispiel nur einen Teil der Seite ausliefert.
Rückgabewert
Promise, das mit der Response des Navigation Preload erfüllt wird. Wurde kein Preload ausgelöst, wird es mit undefined erfüllt.Beispiele
Navigation Preload im activate-Event einschalten
// sw.js
self.addEventListener('activate', (event) => {
event.waitUntil((async () => {
// Nur einschalten, wenn der Browser die Funktion unterstützt
if (self.registration.navigationPreload) {
await self.registration.navigationPreload.enable();
const state = await self.registration.navigationPreload.getState();
console.log('Navigation Preload aktiv:', state.enabled);
}
})());
});
Reihenfolge im fetch-Handler: Cache, dann Preload, dann Netzwerk
// sw.js
self.addEventListener('fetch', (event) => {
if (event.request.mode !== 'navigate') return;
event.respondWith((async () => {
// 1. Cache prüfen
const cached = await caches.match(event.request);
if (cached) return cached;
// 2. Preload-Antwort verwenden, falls vorhanden
const preloaded = await event.preloadResponse;
if (preloaded) return preloaded;
// 3. Auf normalen Netzwerk-Request zurückfallen
return fetch(event.request);
})());
});
Preload-Antwort mit Offline-Rückfallseite und Cache-Aktualisierung
// sw.js
const CACHE = 'seiten-v1';
self.addEventListener('fetch', (event) => {
if (event.request.mode !== 'navigate') return;
event.respondWith((async () => {
try {
const response = (await event.preloadResponse) ?? (await fetch(event.request));
// Kopie im Hintergrund in den Cache legen
const cache = await caches.open(CACHE);
event.waitUntil(cache.put(event.request, response.clone()));
return response;
} catch (err) {
// Offline: Rückfallseite aus dem Cache liefern
return (await caches.match('/offline.html')) ?? Response.error();
}
})());
});
Header-Wert für Preload-Anfragen setzen
// sw.js – der Server kann anhand des Headers z. B. nur den Seiteninhalt liefern
self.addEventListener('activate', (event) => {
event.waitUntil((async () => {
if (!self.registration.navigationPreload) return;
await self.registration.navigationPreload.enable();
await self.registration.navigationPreload.setHeaderValue('content-only');
})());
});
// Wichtig · Fallstricke
- Immer auf
undefinedprüfen: Das Promise liefertundefined, wenn Navigation Preload ausgeschaltet ist, die Anfrage keine Navigation ist oder der Browser die Funktion nicht unterstützt. Deshalb sollte man immerfetch(event.request)als Rückfall vorsehen. - Preload-Antwort nicht ungenutzt lassen: Ist Preload eingeschaltet, aber die Antwort wird nicht verwendet (zum Beispiel weil sie aus dem Cache kommt), gibt Chrome eine Warnung aus: „The service worker navigation preload request was cancelled before 'preloadResponse' settled“. Abhilfe: Das Promise mit
event.waitUntil(event.preloadResponse)an das Event binden. Wer Seiten meist aus dem Cache ausliefert, sollte Navigation Preload besser ganz ausschalten, weil sonst unnötiger Netzwerkverkehr entsteht. - Nur einmal verwendbar: Der Body der zurückgegebenen
Responsekann nur einmal gelesen werden. Wer die Antwort cachen und ausliefern will, muss sie mitresponse.clone()kopieren. - Caching am Server: Wenn der Server je nach Header
Service-Worker-Navigation-Preloadunterschiedliche Inhalte ausliefert, muss erVary: Service-Worker-Navigation-Preloadsetzen. Sonst liefern HTTP-Caches womöglich die falsche Variante aus. - Kompatibilität: Unterstützt in Chromium-Browsern ab Version 59, in Firefox ab 99 und in Safari ab 15.4. Vor dem Einschalten per Feature-Erkennung prüfen:
if (self.registration.navigationPreload). Nur in sicheren Kontexten (HTTPS) verfügbar, da Service Worker HTTPS voraussetzen.