Signatur
Beschreibung
Die schreibgeschützte Eigenschaft notRestoredReasons des Interfaces PerformanceNavigationTiming zeigt, warum eine Seite nicht aus dem Back/Forward-Cache (bfcache) wiederhergestellt wurde. Wird eine Seite aus dem bfcache geladen, erscheint sie beim Zurück- oder Vorwärts-Navigieren sofort. Wenn der Browser das verhindert, muss er die Seite komplett neu laden. Das kostet Ladezeit und verschlechtert Werte wie LCP und INP.
Der Wert ist ein NotRestoredReasons-Objekt mit diesen Eigenschaften:
reasons: Array ausNotRestoredReasonDetails-Objekten. Jedes davon hat eine Eigenschaftreasonmit einem Text wie"unload-listener","response-cache-control-no-store","websocket"oder"masked".children: Array mitNotRestoredReasons-Objekten für eingebettete<iframe>-Elemente, sonstnull.url,src,id,name: Angaben zum Dokument bzw. zum iframe. Beim obersten Dokument sindsrc,idundnamenull.
Die Eigenschaft ist nur bei Navigationen vom Typ "back_forward" gefüllt, die nicht aus dem bfcache bedient wurden. Bei allen anderen Navigationen ist der Wert null. Kommt die Seite tatsächlich aus dem bfcache, entsteht gar kein neuer Navigationseintrag. Das erkennst du stattdessen am pageshow-Event mit event.persisted === true. Typischerweise liest du die Eigenschaft im Real User Monitoring (RUM) aus und schickst sie an ein Analyse-Backend.
Rückgabewert
NotRestoredReasons-Objekt mit den Gründen, warum der bfcache nicht genutzt wurde, oder null, wenn die Navigation keine Vor-/Zurück-Navigation war.Beispiele
Gründe beim Laden der Seite auslesen
const [nav] = performance.getEntriesByType('navigation');
if (nav?.type === 'back_forward' && nav.notRestoredReasons) {
const { url, reasons } = nav.notRestoredReasons;
console.log('Nicht aus dem bfcache geladen:', url);
reasons.forEach(({ reason }) => console.log('Grund:', reason));
} else {
console.log('Keine Gründe vorhanden (keine Vor-/Zurück-Navigation)');
}
Gründe rekursiv inklusive iframes sammeln
const collectReasons = (node, path = 'top') => {
if (!node) return [];
const own = (node.reasons ?? []).map(({ reason }) => ({
frame: node.src ?? node.url ?? path,
reason
}));
const fromChildren = (node.children ?? []).flatMap((child, i) =>
collectReasons(child, `${path} > iframe[${i}]`)
);
return [...own, ...fromChildren];
};
const [nav] = performance.getEntriesByType('navigation');
console.table(collectReasons(nav?.notRestoredReasons));
Per PerformanceObserver an ein RUM-Backend senden
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (!('notRestoredReasons' in entry) || !entry.notRestoredReasons) continue;
const payload = JSON.stringify({
page: location.pathname,
data: entry.notRestoredReasons.toJSON()
});
navigator.sendBeacon('/analytics/bfcache', payload);
}
});
observer.observe({ type: 'navigation', buffered: true });
// Wichtig · Fallstricke
- Browser-Unterstützung: Die Eigenschaft gibt es bisher nur in Chromium-Browsern (ab Chrome/Edge 123). Firefox und Safari kennen sie nicht. Prüfe deshalb vorher mit
'notRestoredReasons' in entry, ob sie vorhanden ist. Frühere Chrome-Testversionen hatten eine abweichende Struktur, zum Beispiel ein Feldblockedund Gründe als einfache Texte. - Datenschutz: Blockiert ein iframe von einem anderen Ursprung den bfcache, erfährst du den Grund nicht. Stattdessen steht dort
"masked". Auch Gründe aus Nutzereinstellungen oder Browser-Interna können als"masked"erscheinen. nullist normal: Bei gewöhnlichen Navigationen ("navigate","reload") und bei Seiten, die erfolgreich aus dem bfcache kamen, bekommst du keine Gründe. Für den Erfolgsfall reagierst du auf daspageshow-Event mitpersisted === true.- Häufige Gründe:
unload-Handler (nutze stattdessenpagehide),Cache-Control: no-store, offene WebSocket- oder WebRTC-Verbindungen sowieBroadcastChannel-Nachrichten. Die Liste der möglichen Gründe hängt vom Browser ab und kann sich ändern. Werte sie deshalb nicht mit einer festen Liste aus.