mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
- Add "unable to preload" pattern to isChunkError for Vite CSS preload failures - Move ConnectionMonitor and ConnectionBanner outside ErrorBoundary so they remain visible when the error boundary catches a render crash - Add test for CSS preload error retry
36 lines
1.0 KiB
TypeScript
36 lines
1.0 KiB
TypeScript
import { type ComponentType, lazy } from "react";
|
|
|
|
export function isChunkError(error: unknown): boolean {
|
|
if (!(error instanceof Error)) return false;
|
|
const msg = error.message.toLowerCase();
|
|
return (
|
|
msg.includes("dynamically imported module") ||
|
|
msg.includes("loading chunk") ||
|
|
msg.includes("loading css chunk") ||
|
|
msg.includes("failed to fetch") ||
|
|
msg.includes("unable to preload")
|
|
);
|
|
}
|
|
|
|
export async function retryDynamicImport<T>(
|
|
importFn: () => Promise<T>,
|
|
retries = 3,
|
|
delay = 1000,
|
|
): Promise<T> {
|
|
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
try {
|
|
return await importFn();
|
|
} catch (error) {
|
|
if (!isChunkError(error) || attempt === retries) throw error;
|
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
}
|
|
}
|
|
throw new Error("unreachable");
|
|
}
|
|
|
|
export function lazyWithRetry<T extends ComponentType<unknown>>(
|
|
importFn: () => Promise<{ default: T }>,
|
|
): React.LazyExoticComponent<T> {
|
|
return lazy(() => retryDynamicImport(importFn));
|
|
}
|