mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
After a deploy the cached SPA shell still references the old chunk filenames. Next.js fetches them, the new server 404s the request, and the user sees the generic error surface — typically with no context other than "Failed to load chunk". The fix on the user's side is a hard reload; before this commit they had to discover it themselves. `AppError` now detects the chunk-load family of errors (`ChunkLoadError`, `Loading chunk`, `Failed to load chunk`, `Failed to fetch dynamically imported module`) and triggers a single `window.location.reload()`. `sessionStorage` gates the auto-reload to once per session so an unrecoverable error doesn't loop into a reload storm. Browsers in strict-privacy mode fall through to the error UI cleanly.
57 lines
1.9 KiB
TypeScript
57 lines
1.9 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect } from "react";
|
|
import { ErrorDetails } from "@/components/error-details";
|
|
|
|
const CHUNK_RELOAD_KEY = "healthlog:chunk-reload-attempted";
|
|
|
|
function isChunkLoadError(err: Error & { digest?: string }): boolean {
|
|
if (err.name === "ChunkLoadError") return true;
|
|
const msg = err.message ?? "";
|
|
return (
|
|
msg.includes("Loading chunk") ||
|
|
msg.includes("Loading CSS chunk") ||
|
|
msg.includes("Failed to load chunk") ||
|
|
msg.includes("Failed to fetch dynamically imported module")
|
|
);
|
|
}
|
|
|
|
export default function AppError({
|
|
error,
|
|
reset,
|
|
}: {
|
|
error: Error & { digest?: string };
|
|
reset: () => void;
|
|
}) {
|
|
useEffect(() => {
|
|
// Surface to any client-side error tracker that's already hooked up.
|
|
if (typeof window !== "undefined") {
|
|
const g = window as typeof window & {
|
|
__healthlog_onError?: (err: Error & { digest?: string }) => void;
|
|
};
|
|
g.__healthlog_onError?.(error);
|
|
}
|
|
|
|
// v1.4.38.3 — auto-recover from a stale-shell chunk-load error.
|
|
// After a deploy the cached shell still references old chunk
|
|
// filenames; they 404 and Next.js surfaces them as `ChunkLoadError`.
|
|
// A single hard reload fetches the new shell + chunk graph.
|
|
// sessionStorage gates the auto-reload so an error we can't recover
|
|
// from (e.g. the new build is also missing the chunk) doesn't loop.
|
|
if (typeof window !== "undefined" && isChunkLoadError(error)) {
|
|
try {
|
|
const already = window.sessionStorage.getItem(CHUNK_RELOAD_KEY);
|
|
if (!already) {
|
|
window.sessionStorage.setItem(CHUNK_RELOAD_KEY, String(Date.now()));
|
|
window.location.reload();
|
|
}
|
|
} catch {
|
|
// sessionStorage can throw under strict privacy modes — fall
|
|
// through to the error UI in that case.
|
|
}
|
|
}
|
|
}, [error]);
|
|
|
|
return <ErrorDetails error={error} reset={reset} />;
|
|
}
|