Skip to content

Commit

Permalink
Detect lazy route discovery manifest version mismatches and trigger r…
Browse files Browse the repository at this point in the history
…eloads
  • Loading branch information
brophdawg11 committed Feb 25, 2025
1 parent 55a42ee commit 3287c95
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 1 deletion.
10 changes: 10 additions & 0 deletions .changeset/moody-onions-hunt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@remix-run/react": patch
"@remix-run/server-runtime": patch
---

When using Lazy Route Disscovery (`future.v3_lazyRouteDiscovery`), Remix will now detect manifest version mismatches after a new deploy and trigger a document reload to sync up any active client sessions with the newly deployed version

- On navigations to undiscovered routes, this mismatch will trigger a document reload of the destination path
- On `fetcher` calls to undiscovered routes, this mismatch will trigger a document reload of the current path
- While performing Eager Route Discovery on rendered `<Link>` components, mismatches will result in a no-op
45 changes: 44 additions & 1 deletion packages/remix-react/fog-of-war.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,13 @@ export function getPatchRoutesOnNavigationFunction(
if (!isFogOfWarEnabled(future, isSpaMode)) {
return undefined;
}
return async ({ path, patch, signal }) => {
return async ({ path, patch, signal, fetcherKey }) => {
if (discoveredPaths.has(path)) {
return;
}
await fetchAndApplyManifestPatches(
[path],
fetcherKey ? window.location.href : path,
manifest,
routeModules,
future,
Expand Down Expand Up @@ -139,6 +140,7 @@ export function useFogOFWarDiscovery(
try {
await fetchAndApplyManifestPatches(
lazyPaths,
null,
manifest,
routeModules,
future,
Expand Down Expand Up @@ -201,8 +203,11 @@ export function useFogOFWarDiscovery(
}, [future, isSpaMode, manifest, routeModules, router]);
}

const MANIFEST_VERSION_STORAGE_KEY = "remix-manifest-version";

export async function fetchAndApplyManifestPatches(
paths: string[],
errorReloadPath: string | null,
manifest: AssetsManifest,
routeModules: RouteModules,
future: FutureConfig,
Expand Down Expand Up @@ -230,10 +235,48 @@ export async function fetchAndApplyManifestPatches(

if (!res.ok) {
throw new Error(`${res.status} ${res.statusText}`);
} else if (
res.status === 204 &&
res.headers.has("X-Remix-Reload-Document")
) {
if (!errorReloadPath) {
// No-op during eager route discovery so we will trigger a hard reload
// of the destination during the next navigation instead of reloading
// while the user is sitting on the current page. Slightly more
// disruptive on fetcher calls because we reload the current page, but
// it's better than the `React.useContext` error that occurs without
// this detection.
console.warn(
"Detected a manifest version mismatch during eager route discovery. " +
"The next navigation/fetch to an undiscovered route will result in " +
"a new document navigation to sync up with the latest manifest."
);
return;
}

// This will hard reload the destination path on navigations, or the
// current path on fetcher calls
if (
sessionStorage.getItem(MANIFEST_VERSION_STORAGE_KEY) ===
manifest.version
) {
// We've already tried fixing for this version, don' try again to
// avoid loops - just let this navigation/fetch 404
console.error(
"Unable to discover routes due to manifest version mismatch."
);
return;
}

sessionStorage.setItem(MANIFEST_VERSION_STORAGE_KEY, manifest.version);
window.location.href = errorReloadPath;
throw new Error("Detected manifest version mismatch, reloading...");
} else if (res.status >= 400) {
throw new Error(await res.text());
}

// Reset loop-detection on a successful response
sessionStorage.removeItem(MANIFEST_VERSION_STORAGE_KEY);
serverPatches = (await res.json()) as AssetsManifest["routes"];
} catch (e) {
if (signal?.aborted) return;
Expand Down
9 changes: 9 additions & 0 deletions packages/remix-server-runtime/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,15 @@ async function handleManifestRequest(
routes: ServerRoute[],
url: URL
) {
if (build.assets.version !== url.searchParams.get("version")) {
return new Response(null, {
status: 204,
headers: {
"X-Remix-Reload-Document": "true",
},
});
}

let patches: Record<string, EntryRoute> = {};

if (url.searchParams.has("p")) {
Expand Down

0 comments on commit 3287c95

Please sign in to comment.