83 lines
2.6 KiB
TypeScript
83 lines
2.6 KiB
TypeScript
|
|
"use client";
|
||
|
|
|
||
|
|
import { useEffect } from "react";
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Component to handle ChunkLoadError automatically
|
||
|
|
* When a chunk fails to load (usually after deployment),
|
||
|
|
* this component will force refresh the page once
|
||
|
|
*/
|
||
|
|
export default function ChunkLoadErrorHandler() {
|
||
|
|
useEffect(() => {
|
||
|
|
// Key to track if we've already refreshed for this error
|
||
|
|
const REFRESH_KEY = "chunk-load-error-refreshed";
|
||
|
|
|
||
|
|
// Handle unhandled promise rejections (for dynamic imports)
|
||
|
|
const handlePromiseRejection = (event: PromiseRejectionEvent) => {
|
||
|
|
const error = event.reason;
|
||
|
|
|
||
|
|
// Check if it's a ChunkLoadError
|
||
|
|
if (
|
||
|
|
error?.name === "ChunkLoadError" ||
|
||
|
|
error?.message?.includes("Loading chunk") ||
|
||
|
|
error?.message?.includes("ChunkLoadError") ||
|
||
|
|
error?.message?.includes("Failed to fetch dynamically imported module") ||
|
||
|
|
error?.message?.includes("failed to load resource")
|
||
|
|
) {
|
||
|
|
handleChunkLoadError();
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// Handle regular errors
|
||
|
|
const handleError = (event: ErrorEvent) => {
|
||
|
|
const error = event.error;
|
||
|
|
|
||
|
|
// Check if it's a ChunkLoadError
|
||
|
|
if (
|
||
|
|
error?.name === "ChunkLoadError" ||
|
||
|
|
event.message?.includes("Loading chunk") ||
|
||
|
|
event.message?.includes("ChunkLoadError") ||
|
||
|
|
event.message?.includes("Failed to fetch dynamically imported module")
|
||
|
|
) {
|
||
|
|
handleChunkLoadError();
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleChunkLoadError = () => {
|
||
|
|
// Check if we've already refreshed
|
||
|
|
const hasRefreshed = sessionStorage.getItem(REFRESH_KEY);
|
||
|
|
|
||
|
|
if (!hasRefreshed) {
|
||
|
|
console.log("ChunkLoadError detected. Refreshing page...");
|
||
|
|
|
||
|
|
// Mark that we've refreshed
|
||
|
|
sessionStorage.setItem(REFRESH_KEY, "true");
|
||
|
|
|
||
|
|
// Force reload the page (bypassing cache)
|
||
|
|
window.location.reload();
|
||
|
|
} else {
|
||
|
|
console.error("ChunkLoadError persists after refresh. There might be a deeper issue.");
|
||
|
|
|
||
|
|
// Clear the flag after 30 seconds in case user navigates away and comes back
|
||
|
|
setTimeout(() => {
|
||
|
|
sessionStorage.removeItem(REFRESH_KEY);
|
||
|
|
}, 30000);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// Add event listeners
|
||
|
|
window.addEventListener("error", handleError);
|
||
|
|
window.addEventListener("unhandledrejection", handlePromiseRejection);
|
||
|
|
|
||
|
|
// Cleanup event listeners
|
||
|
|
return () => {
|
||
|
|
window.removeEventListener("error", handleError);
|
||
|
|
window.removeEventListener("unhandledrejection", handlePromiseRejection);
|
||
|
|
};
|
||
|
|
}, []);
|
||
|
|
|
||
|
|
// This component doesn't render anything
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|