const RELOAD_FLAG_KEY = '__chunk_reload_at' const RELOAD_COOLDOWN_MS = 10_000 function shouldReload(): boolean { try { const raw = sessionStorage.getItem(RELOAD_FLAG_KEY) if (!raw) return true const at = Number(raw) if (!Number.isFinite(at)) return true return Date.now() - at > RELOAD_COOLDOWN_MS } catch { return true } } function markReload(): void { try { sessionStorage.setItem(RELOAD_FLAG_KEY, String(Date.now())) } catch { // ignore storage failures (private mode, quota) } } export function reloadForStaleChunk(): boolean { if (!shouldReload()) return false markReload() location.reload() return true } const CHUNK_ERROR_PATTERNS = [ /Failed to fetch dynamically imported module/i, /error loading dynamically imported module/i, /Importing a module script failed/i, /Unable to preload CSS/i, ] export function isChunkLoadError(err: unknown): boolean { const msg = err instanceof Error ? err.message : typeof err === 'string' ? err : '' return CHUNK_ERROR_PATTERNS.some((re) => re.test(msg)) } export function registerChunkReloadHandlers(): void { window.addEventListener('vite:preloadError', (event) => { if (reloadForStaleChunk()) { event.preventDefault() } }) }