You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
50 lines
1.7 KiB
50 lines
1.7 KiB
/** |
|
* After a deploy, hashed chunks from the previous build are removed. A tab that still runs old JS |
|
* (HTTP cache, or a service worker precache race) can 404 on `import()`. One reload usually picks |
|
* up fresh `index.html` and the new asset graph. |
|
*/ |
|
const SESSION_KEY = 'jumble:stale-chunk-reload' |
|
|
|
export function isChunkLoadFailureMessage(message: string): boolean { |
|
const m = message.toLowerCase() |
|
return ( |
|
m.includes('failed to fetch dynamically imported module') || |
|
m.includes('error loading dynamically imported module') || |
|
m.includes('importing a module script failed') || |
|
// Safari / some WebKit builds |
|
(m.includes('dynamically imported module') && (m.includes('failed') || m.includes('error'))) |
|
) |
|
} |
|
|
|
/** Returns true if a reload was scheduled (at most once per session). */ |
|
export function tryStaleChunkReloadOnce(): boolean { |
|
if (typeof window === 'undefined') return false |
|
try { |
|
if (sessionStorage.getItem(SESSION_KEY)) return false |
|
sessionStorage.setItem(SESSION_KEY, '1') |
|
} catch { |
|
return false |
|
} |
|
window.location.reload() |
|
return true |
|
} |
|
|
|
export function installStaleBuildChunkRecovery(): void { |
|
if (typeof window === 'undefined') return |
|
|
|
window.addEventListener('unhandledrejection', (event) => { |
|
const r = event.reason |
|
const msg = |
|
typeof r === 'string' ? r : r instanceof Error ? r.message : String(r ?? '') |
|
if (!isChunkLoadFailureMessage(msg)) return |
|
event.preventDefault() |
|
tryStaleChunkReloadOnce() |
|
}) |
|
|
|
window.addEventListener('error', (event) => { |
|
const msg = event.message ?? '' |
|
if (!isChunkLoadFailureMessage(msg)) return |
|
event.preventDefault() |
|
tryStaleChunkReloadOnce() |
|
}) |
|
}
|
|
|