Skip to content
Source
Sign inSign up

chunkReloadGuard.ts

36 lines1.4 KB

1// Deploys and desktop server swaps can invalidate lazy chunks; one reload fetches the fresh index.
2// Keyed by build and kept across boots: a chunk loaded after boot can fail on every visit.
3const CHUNK_RELOAD_GUARD_KEY = "t3code:chunk-load-reloaded";
4​
5export function reloadOnceForChunkLoadError(
6 getStorage: () => Storage = () => window.sessionStorage,
7 reload: () => void = () => window.location.reload(),
8 build = import.meta.env.APP_VERSION,
9): boolean {
10 let alreadyReloaded: boolean;
11 try {
12 const storage = getStorage();
13 alreadyReloaded = storage.getItem(CHUNK_RELOAD_GUARD_KEY) === build;
14 if (!alreadyReloaded) storage.setItem(CHUNK_RELOAD_GUARD_KEY, build);
15 } catch {
16 // Without storage, the reload guard cannot prevent an infinite loop.
17 return false;
18 }
19 if (alreadyReloaded) return false;
20 reload();
21 return true;
23​
24// Browsers cache a failed dynamic import per document, so only a reload can retry it.
25const CHUNK_LOAD_ERROR_PREFIXES = [
26 "Failed to fetch dynamically imported module", // Chromium
27 "error loading dynamically imported module", // Firefox
28 "Importing a module script failed", // Safari
29];
30​
31export function isChunkLoadError(error: unknown): boolean {
32 const message = error instanceof Error ? error.message : undefined;
33 return (
34 message !== undefined && CHUNK_LOAD_ERROR_PREFIXES.some((prefix) => message.startsWith(prefix))
35 );