Files
geo/apps/admin-web/src/lib/chunk-reload.ts
T
root 18011a7892 fix(admin-web): auto-reload on stale dynamic-import chunks after deploy
Listen for vite:preloadError and router onError, force a one-shot reload
(10s cooldown via sessionStorage) when a hashed lazy-loaded module 404s
because a new deploy replaced it. Eliminates the user-visible "Failed to
fetch dynamically imported module" error on login and route navigation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 17:47:51 +08:00

55 lines
1.3 KiB
TypeScript

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()
}
})
}