fix(web): bound lazy route recovery

This commit is contained in:
lingniu
2026-07-16 05:29:08 +08:00
parent b21f9a60cd
commit d669531128
5 changed files with 97 additions and 5 deletions

View File

@@ -8,7 +8,11 @@ const CHUNK_RELOAD_COOLDOWN_MS = 2 * 60_000;
export function isRouteChunkError(error: unknown) {
const message = error instanceof Error ? `${error.name} ${error.message}` : String(error);
return /ChunkLoadError|Loading chunk .+ failed|Failed to fetch dynamically imported module|Importing a module script failed|error loading dynamically imported module/i.test(message);
return /ChunkLoadError|RouteChunkLoadTimeoutError|Route chunk load timed out|Loading chunk .+ failed|Failed to fetch dynamically imported module|Importing a module script failed|error loading dynamically imported module/i.test(message);
}
function isRouteChunkTimeout(error: unknown) {
return error instanceof Error && (error.name === 'RouteChunkLoadTimeoutError' || /Route chunk load timed out/i.test(error.message));
}
function canAutoReload(routeKey: string) {
@@ -52,12 +56,13 @@ class RecoverableRouteBoundary extends Component<{ children: ReactNode; routeKey
const { error } = this.state;
if (!error) return this.props.children;
const chunkError = isRouteChunkError(error);
const chunkTimeout = isRouteChunkTimeout(error);
return <section className="v2-route-error" role="alert">
<span><IconAlertTriangle /></span>
<div>
<small>{chunkError ? '检测到页面版本更新' : '页面运行异常'}</small>
<h2>{chunkError ? '正在等待加载最新页面资源' : '当前模块暂时无法显示'}</h2>
<p>{chunkError ? '通常是发布后旧标签页仍引用上一版本资源。刷新后会恢复,不会丢失服务端数据。' : '页面已被安全隔离,侧栏和其他模块仍可使用。更换筛选条件会自动重试,也可刷新当前页面。'}</p>
<small>{chunkTimeout ? '页面资源加载超时' : chunkError ? '检测到页面版本更新' : '页面运行异常'}</small>
<h2>{chunkTimeout ? '当前模块没有在预期时间内加载完成' : chunkError ? '正在等待加载最新页面资源' : '当前模块暂时无法显示'}</h2>
<p>{chunkTimeout ? '系统已等待并尝试恢复,可能是网络暂时不稳定。刷新后会重新加载当前模块,不会丢失服务端数据。' : chunkError ? '通常是发布后旧标签页仍引用上一版本资源。刷新后会恢复,不会丢失服务端数据。' : '页面已被安全隔离,侧栏和其他模块仍可使用。更换筛选条件会自动重试,也可刷新当前页面。'}</p>
<code>{error.message || error.name}</code>
<footer>
<button type="button" onClick={() => window.location.reload()}><IconRefresh /></button>