Homepage bootstrap never escaped the loading shell when a new web image changed chunk hashes. Stamp deploymentId, stop caching chat HTML, and hard-reload failed chunk loads once. Co-authored-by: Cursor <cursoragent@cursor.com>
51 lines
1.6 KiB
TypeScript
51 lines
1.6 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect } from "react";
|
|
|
|
import {
|
|
consumeStaleClientReload,
|
|
isChunkLoadFailure,
|
|
shouldReloadFrozenBootstrap,
|
|
} from "@/lib/stale-client-recovery";
|
|
|
|
function reloadIfStale() {
|
|
try {
|
|
if (!consumeStaleClientReload(sessionStorage)) return;
|
|
} catch {
|
|
return;
|
|
}
|
|
window.location.reload();
|
|
}
|
|
|
|
export function StaleClientRecovery() {
|
|
useEffect(() => {
|
|
const onError = (event: ErrorEvent) => {
|
|
const message = `${event.message} ${event.filename ?? ""} ${event.error instanceof Error ? event.error.message : ""}`;
|
|
if (isChunkLoadFailure(message)) reloadIfStale();
|
|
};
|
|
const onRejection = (event: PromiseRejectionEvent) => {
|
|
const reason = event.reason;
|
|
const message = reason instanceof Error ? reason.message : String(reason ?? "");
|
|
if (isChunkLoadFailure(message)) reloadIfStale();
|
|
};
|
|
const onPageShow = (event: PageTransitionEvent) => {
|
|
if (shouldReloadFrozenBootstrap({
|
|
persisted: event.persisted,
|
|
loadingBusy: Boolean(document.querySelector('main.app-loading[aria-busy="true"]')),
|
|
loadingError: Boolean(document.querySelector("main.app-loading-error")),
|
|
})) {
|
|
reloadIfStale();
|
|
}
|
|
};
|
|
window.addEventListener("error", onError);
|
|
window.addEventListener("unhandledrejection", onRejection);
|
|
window.addEventListener("pageshow", onPageShow);
|
|
return () => {
|
|
window.removeEventListener("error", onError);
|
|
window.removeEventListener("unhandledrejection", onRejection);
|
|
window.removeEventListener("pageshow", onPageShow);
|
|
};
|
|
}, []);
|
|
return null;
|
|
}
|