Signatur
Beschreibung
Die schreibgeschützte Eigenschaft children der Schnittstelle NotRestoredReasons enthält für jedes direkt eingebettete <iframe> des Dokuments ein eigenes NotRestoredReasons-Objekt. Diese Kindobjekte haben dieselbe Struktur wie das Elternobjekt (blocked, reasons, url, src, id, name, children). Dadurch lässt sich ein beliebig tiefer Baum verschachtelter Frames rekursiv abbilden.
Gebraucht wird die Eigenschaft, um herauszufinden, welcher Frame verhindert hat, dass eine Seite bei einer Zurück- oder Vorwärts-Navigation aus dem Back/Forward-Cache (bfcache) wiederhergestellt wurde. Oft liegt der Grund nicht in der Hauptseite, sondern in einem eingebetteten Widget, einer Werbung oder einem Chat-Fenster, das zum Beispiel einen unload-Listener registriert.
An das Objekt kommt man über PerformanceNavigationTiming.notRestoredReasons, also über den Navigationseintrag aus performance.getEntriesByType("navigation"). Hat ein Frame keine Kind-Frames, ist children ein leeres Array. Liegt das Dokument in einem Cross-Origin-iframe, ist der Wert null, damit keine Informationen über fremde Ursprünge nach außen gelangen.
Rückgabewert
NotRestoredReasons-Objekten, eines pro eingebettetem iframe. Hat der Frame keine Kinder, ist das Array leer. Bei Cross-Origin-iframes ist der Wert null.Beispiele
Kind-Frames des Navigationseintrags auslesen
const [nav] = performance.getEntriesByType("navigation");
const nrr = nav?.notRestoredReasons;
if (nrr) {
console.log(`Hauptframe blockiert: ${nrr.blocked}`);
for (const child of nrr.children ?? []) {
console.log(child.src, child.blocked, child.reasons?.map((r) => r.reason));
}
} else {
console.log("Keine Daten (keine Back/Forward-Navigation oder nicht unterstützt)");
}
Rekursiv alle blockierenden Frames finden
const collectBlockers = (node, path = "top") => {
if (!node) return [];
const own = node.blocked
? [{ path, url: node.url ?? node.src, reasons: (node.reasons ?? []).map((r) => r.reason) }]
: [];
const nested = (node.children ?? []).flatMap((child, i) =>
collectBlockers(child, `${path} > iframe[${child.id || child.name || i}]`)
);
return [...own, ...nested];
};
const [nav] = performance.getEntriesByType("navigation");
console.table(collectBlockers(nav?.notRestoredReasons));
bfcache-Blockaden an ein Analyse-Backend melden
window.addEventListener("pageshow", (event) => {
if (event.persisted) return; // aus dem bfcache wiederhergestellt – alles gut
const [nav] = performance.getEntriesByType("navigation");
if (nav?.type !== "back_forward" || !nav.notRestoredReasons) return;
const serialize = (n) => n && {
src: n.src,
blocked: n.blocked,
reasons: n.reasons?.map((r) => r.reason) ?? null,
children: n.children?.map(serialize) ?? null,
};
navigator.sendBeacon(
"/analytics/bfcache",
JSON.stringify(serialize(nav.notRestoredReasons))
);
});
// Wichtig · Fallstricke
- Browser-Unterstützung: Nur in Chromium-Browsern ab Version 123 verfügbar (experimentell). Firefox und Safari kennen
notRestoredReasonsnicht. Prüfe deshalb immer mit Optional Chaining (nav?.notRestoredReasons?.children). nullstatt Array: Bei Cross-Origin-iframes istchildren(ebenso wiereasons)null. Verwendechildren ?? [], bevor du darüber iterierst.- Datenschutz: Blockiert ein Cross-Origin-Frame den bfcache, meldet der Hauptframe nur den Grund
"masked". Die tatsächliche Ursache bleibt verborgen. notRestoredReasonsselbst istnull, wenn es keine Back/Forward-Navigation war oder die Seite erfolgreich aus dem bfcache kam.childrensteht also nur zur Verfügung, wenn es tatsächlich etwas zu melden gibt.- Das Array enthält nur direkte Kind-Frames. Tiefer verschachtelte iframes erreichst du nur, indem du rekursiv durch die
childrender Kindobjekte gehst.