From f642ef1d56fbfa70e67eebd69cd8a60c399675ac Mon Sep 17 00:00:00 2001 From: hailin Date: Wed, 4 Mar 2026 18:50:22 -0800 Subject: [PATCH] =?UTF-8?q?fix(admin-web):=20=E6=B7=BB=E5=8A=A0=20global-e?= =?UTF-8?q?rror.tsx=20=E4=BF=AE=E5=A4=8D=E9=83=A8=E7=BD=B2=E5=90=8E=20Serv?= =?UTF-8?q?er=20Action=20=E5=B4=A9=E6=BA=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题:每次重新部署容器后,浏览器持有旧 bundle,Next.js App Router 内部 Server Action ID("r"/"multi")与新服务器不匹配,导致客户端抛出 未捕获异常,触发全屏 "Application error"(周期性崩溃根因)。 修复: - 添加 src/app/global-error.tsx(根级错误边界),检测到 stale bundle 相关错误时自动调用 window.location.reload(),无感知恢复 - 添加 src/app/(admin)/error.tsx(admin 路由段错误边界),同样自动刷新 - 两个边界均提供「立即刷新」「重试」按钮,防止极端情况下自动刷新失效 Co-Authored-By: Claude Sonnet 4.6 --- frontend/admin-web/src/app/(admin)/error.tsx | 92 ++++++++++++++++ frontend/admin-web/src/app/global-error.tsx | 105 +++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 frontend/admin-web/src/app/(admin)/error.tsx create mode 100644 frontend/admin-web/src/app/global-error.tsx diff --git a/frontend/admin-web/src/app/(admin)/error.tsx b/frontend/admin-web/src/app/(admin)/error.tsx new file mode 100644 index 0000000..008a73c --- /dev/null +++ b/frontend/admin-web/src/app/(admin)/error.tsx @@ -0,0 +1,92 @@ +'use client'; + +import { useEffect } from 'react'; + +/** + * Admin 路由段错误边界 + * + * 捕获 (admin) 路由内的客户端异常。 + * 当检测到 Next.js stale bundle / Server Action 不匹配错误时自动刷新页面。 + */ +export default function AdminError({ + error, + reset, +}: { + error: Error & { digest?: string }; + reset: () => void; +}) { + useEffect(() => { + const msg = error?.message ?? ''; + const isStaleBundle = + msg.includes('Server Action') || + msg.includes('Failed to find') || + msg.includes('An unexpected response was received') || + (error?.digest ?? '').startsWith('NEXT_'); + + if (isStaleBundle) { + window.location.reload(); + } + }, [error]); + + return ( +
+
+
⚠️
+

+ 页面加载出错 +

+

+ 检测到新版本,正在自动刷新… +

+
+ + +
+
+
+ ); +} diff --git a/frontend/admin-web/src/app/global-error.tsx b/frontend/admin-web/src/app/global-error.tsx new file mode 100644 index 0000000..05e84ce --- /dev/null +++ b/frontend/admin-web/src/app/global-error.tsx @@ -0,0 +1,105 @@ +'use client'; + +/** + * Next.js App Router 根级错误边界 + * + * 捕获未处理的客户端异常,避免显示 Next.js 默认的 + * "Application error: a client-side exception has occurred" 全屏崩溃页。 + * + * 常见触发场景: + * - 重新部署后,浏览器仍持有旧 bundle,内部 Server Action ID("r" / "multi") + * 已不匹配新服务器构建 → Failed to find Server Action → 客户端异常 + * - 此时自动刷新页面即可恢复正常(加载新 bundle) + * + * global-error.tsx 必须自带 ,因为它会替换根 layout。 + */ + +import { useEffect } from 'react'; + +export default function GlobalError({ + error, + reset, +}: { + error: Error & { digest?: string }; + reset: () => void; +}) { + useEffect(() => { + // 检测 Next.js stale bundle 导致的 Server Action 不匹配错误 + // 自动刷新页面以加载新版本 + const msg = error?.message ?? ''; + const isStaleBundle = + msg.includes('Server Action') || + msg.includes('Failed to find') || + msg.includes('An unexpected response was received') || + (error?.digest ?? '').startsWith('NEXT_'); + + if (isStaleBundle) { + window.location.reload(); + } + }, [error]); + + return ( + + +
+
⚠️
+

+ 页面加载出错 +

+

+ 检测到新版本,正在自动刷新… +

+
+ + +
+
+ + + ); +}