From c147d7971b14d8790115e8accb055e9698024073 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 21 Feb 2026 06:06:19 +0800 Subject: [PATCH] fix: auto-recover from client runtime/server-action mismatch errors --- app/layout.tsx | 45 +++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/app/layout.tsx b/app/layout.tsx index 07f158a9c..29935272d 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -105,22 +105,43 @@ const CHUNK_ERROR_RECOVERY_SCRIPT = `\ var hasReloaded = safeGetSessionStorage('chunk-reload-attempted'); - window.addEventListener('error', function(event) { - var isChunkError = event.message && ( - event.message.includes('Failed to load chunk') || - event.message.includes('Loading chunk') || - event.message.includes('/_next/static/chunks/') + function shouldAutoRecover(message) { + if (!message) return false; + return ( + message.includes('Failed to load chunk') || + message.includes('Loading chunk') || + message.includes('/_next/static/chunks/') || + message.includes('Failed to find Server Action') || + message.includes('Server Components render') || + message.includes('Application error: a client-side exception') ); - - if (isChunkError && !hasReloaded) { - console.warn('[ChunkError] 检测到chunk加载失败,自动刷新页面...'); - safeSetSessionStorage('chunk-reload-attempted', 'true'); - setTimeout(function() { - window.location.reload(); - }, 1000); + } + + function triggerAutoRecover(reason) { + if (hasReloaded) return; + console.warn('[RuntimeRecover] 检测到前端运行时异常,自动刷新页面...', reason || ''); + safeSetSessionStorage('chunk-reload-attempted', 'true'); + setTimeout(function() { + window.location.reload(); + }, 800); + } + + window.addEventListener('error', function(event) { + if (shouldAutoRecover(event && event.message)) { + triggerAutoRecover(event && event.message); } }, true); + window.addEventListener('unhandledrejection', function(event) { + var reason = event && event.reason; + var reasonText = ''; + if (typeof reason === 'string') reasonText = reason; + else if (reason && typeof reason.message === 'string') reasonText = reason.message; + if (shouldAutoRecover(reasonText)) { + triggerAutoRecover(reasonText); + } + }); + // 页面加载成功后清除标记 window.addEventListener('load', function() { setTimeout(function() {