fix: Add ChunkLoadError handling with automatic page reload
- Detect ChunkLoadError in global error handler - Automatically clear Next.js cache and reload page when chunk errors occur - Add proper cache headers for Next.js static chunks (immutable caching) - Handle ChunkLoadError in both error events and unhandled promise rejections - Prevents users from seeing chunk load errors after deployments Fixes production issue where admin page fails to load after new deployment due to stale chunks in browser cache
This commit is contained in:
@@ -61,6 +61,26 @@ const nextConfig: NextConfig = {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
// Next.js chunks - ensure proper caching with versioning
|
||||
source: "/_next/static/chunks/:path*",
|
||||
headers: [
|
||||
{
|
||||
key: "Cache-Control",
|
||||
value: "public, max-age=31536000, immutable",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
// Next.js static files - ensure proper caching
|
||||
source: "/_next/static/:path*",
|
||||
headers: [
|
||||
{
|
||||
key: "Cache-Control",
|
||||
value: "public, max-age=31536000, immutable",
|
||||
},
|
||||
],
|
||||
},
|
||||
// Security headers are handled in src/proxy.ts middleware (single source of truth)
|
||||
// This ensures consistent headers across all routes and avoids conflicts
|
||||
];
|
||||
|
||||
@@ -123,11 +123,55 @@ export default function RootLayout({
|
||||
const originalWarn = console.warn;
|
||||
const originalLog = console.log;
|
||||
|
||||
// Handle ChunkLoadError - automatically reload page
|
||||
let chunkErrorReloadAttempted = false;
|
||||
const handleChunkLoadError = function(error) {
|
||||
const message = error?.message || error?.toString() || '';
|
||||
const lowerMessage = message.toLowerCase();
|
||||
|
||||
// Check if this is a ChunkLoadError
|
||||
if (
|
||||
(lowerMessage.includes('chunkloaderror') ||
|
||||
lowerMessage.includes('failed to load chunk') ||
|
||||
lowerMessage.includes('loading chunk') ||
|
||||
error?.name === 'ChunkLoadError') &&
|
||||
!chunkErrorReloadAttempted
|
||||
) {
|
||||
chunkErrorReloadAttempted = true;
|
||||
console.warn('ChunkLoadError detected - reloading page to fetch latest chunks...');
|
||||
|
||||
// Clear Next.js cache and reload
|
||||
if ('caches' in window) {
|
||||
caches.keys().then(function(names) {
|
||||
for (let name of names) {
|
||||
if (name.includes('nextjs') || name.includes('_next')) {
|
||||
caches.delete(name);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Reload after a short delay to allow cache clearing
|
||||
setTimeout(function() {
|
||||
window.location.reload();
|
||||
}, 100);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Intercept uncaught errors
|
||||
window.addEventListener('error', function(event) {
|
||||
const message = event.message || '';
|
||||
const lowerMessage = message.toLowerCase();
|
||||
|
||||
// Handle ChunkLoadError first
|
||||
if (handleChunkLoadError(event.error || event)) {
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Suppress OuterLayoutRouter key warnings
|
||||
if (
|
||||
(lowerMessage.includes('key') || lowerMessage.includes('unique')) &&
|
||||
@@ -153,6 +197,12 @@ export default function RootLayout({
|
||||
const message = reason?.message || reason?.toString() || '';
|
||||
const lowerMessage = message.toLowerCase();
|
||||
|
||||
// Handle ChunkLoadError in promise rejections
|
||||
if (handleChunkLoadError(reason)) {
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Suppress Supabase NetworkErrors
|
||||
if (
|
||||
lowerMessage.includes('networkerror') &&
|
||||
|
||||
Reference in New Issue
Block a user