diff --git a/.changeset/shy-ducks-repeat.md b/.changeset/shy-ducks-repeat.md
new file mode 100644
index 00000000000..f8db29a9e9d
--- /dev/null
+++ b/.changeset/shy-ducks-repeat.md
@@ -0,0 +1,8 @@
+---
+"@remix-run/react": patch
+"@remix-run/server-runtime": patch
+---
+
+- Fog of War: Simplify implementation now that React Router handles slug/splat edge cases and tracks previously disscovered routes (see https://github.com/remix-run/react-router/pull/11883)
+ - This changes the return signature of the internal `__manifest` endpoint since we no longer need the `notFoundPaths` field
+- Fog of War: Update to use renamed `unstable_patchRoutesOnNavigation` function in RR (see https://github.com/remix-run/react-router/pull/11888)
\ No newline at end of file
diff --git a/integration/fog-of-war-test.ts b/integration/fog-of-war-test.ts
index 70f209b238a..4a3c4b77908 100644
--- a/integration/fog-of-war-test.ts
+++ b/integration/fog-of-war-test.ts
@@ -818,6 +818,7 @@ test.describe("Fog of War", () => {
"routes/parent._a._b",
"routes/parent._a._b._index",
]);
+ expect(manifestRequests).toEqual([]);
// Without pre-loading the index, we'd "match" `/parent` to just the
// parent route client side and never fetch the children pathless/index routes
@@ -841,6 +842,475 @@ test.describe("Fog of War", () => {
]);
});
+ test("detects higher-ranking static routes on the server when a slug match is already known by the client", async ({
+ page,
+ }) => {
+ let fixture = await createFixture({
+ config: {
+ future: {
+ unstable_lazyRouteDiscovery: true,
+ },
+ },
+ files: {
+ "app/root.tsx": js`
+ import { Link, Outlet, Scripts } from "@remix-run/react";
+
+ export default function Root() {
+ return (
+
+
+
+
+ /something
+
+
+
+
+
+ );
+ }
+ `,
+
+ "app/routes/_index.tsx": js`
+ export default function Index() {
+ return Index
+ }
+ `,
+ "app/routes/$slug.tsx": js`
+ import { Link } from "@remix-run/react";
+ export default function Component() {
+ return (
+ <>
+ Slug ;
+ Go to /static
+ >
+ );
+ }
+ `,
+ "app/routes/static.tsx": js`
+ export default function Component() {
+ return Static ;
+ }
+ `,
+ },
+ });
+ let appFixture = await createAppFixture(fixture);
+ let app = new PlaywrightFixture(appFixture, page);
+
+ let manifestRequests: string[] = [];
+ page.on("request", (req) => {
+ if (req.url().includes("/__manifest")) {
+ manifestRequests.push(req.url());
+ }
+ });
+
+ await app.goto("/", true);
+ expect(await app.getHtml("#index")).toMatch("Index");
+ expect(
+ await page.evaluate(() =>
+ Object.keys((window as any).__remixManifest.routes)
+ )
+ ).toEqual(["root", "routes/_index", "routes/$slug"]);
+ expect(manifestRequests).toEqual([
+ expect.stringMatching(/\/__manifest\?version=[a-z0-9]{8}&p=%2Fsomething/),
+ ]);
+ manifestRequests = [];
+
+ await app.clickLink("/something");
+ await page.waitForSelector("#slug");
+ expect(await app.getHtml("#slug")).toMatch("Slug");
+ expect(manifestRequests).toEqual([]);
+
+ // This will require a new fetch for the /static route
+ await app.clickLink("/static");
+ await page.waitForSelector("#static");
+ expect(await app.getHtml("#static")).toMatch("Static");
+ expect(manifestRequests).toEqual([
+ expect.stringMatching(/\/__manifest\?version=[a-z0-9]{8}&p=%2Fstatic/),
+ ]);
+ expect(
+ await page.evaluate(() =>
+ Object.keys((window as any).__remixManifest.routes)
+ )
+ ).toEqual(["root", "routes/_index", "routes/$slug", "routes/static"]);
+ });
+
+ test("detects higher-ranking static routes on the server when a splat match is already known by the client", async ({
+ page,
+ }) => {
+ let fixture = await createFixture({
+ config: {
+ future: {
+ unstable_lazyRouteDiscovery: true,
+ },
+ },
+ files: {
+ "app/root.tsx": js`
+ import { Link, Outlet, Scripts } from "@remix-run/react";
+
+ export default function Root() {
+ return (
+
+
+
+
+ /something
+
+
+
+
+
+ );
+ }
+ `,
+
+ "app/routes/_index.tsx": js`
+ export default function Index() {
+ return Index
+ }
+ `,
+ "app/routes/$.tsx": js`
+ import { Link } from "@remix-run/react";
+ export default function Component() {
+ return (
+ <>
+ Splat ;
+ Go to /static
+ >
+ );
+ }
+ `,
+ "app/routes/static.tsx": js`
+ export default function Component() {
+ return Static ;
+ }
+ `,
+ },
+ });
+ let appFixture = await createAppFixture(fixture);
+ let app = new PlaywrightFixture(appFixture, page);
+
+ let manifestRequests: string[] = [];
+ page.on("request", (req) => {
+ if (req.url().includes("/__manifest")) {
+ manifestRequests.push(req.url());
+ }
+ });
+
+ await app.goto("/", true);
+ expect(await app.getHtml("#index")).toMatch("Index");
+ expect(
+ await page.evaluate(() =>
+ Object.keys((window as any).__remixManifest.routes)
+ )
+ ).toEqual(["root", "routes/_index", "routes/$"]);
+ expect(manifestRequests).toEqual([
+ expect.stringMatching(/\/__manifest\?version=[a-z0-9]{8}&p=%2Fsomething/),
+ ]);
+ manifestRequests = [];
+
+ await app.clickLink("/something");
+ await page.waitForSelector("#splat");
+ expect(await app.getHtml("#splat")).toMatch("Splat");
+ expect(manifestRequests).toEqual([]);
+
+ // This will require a new fetch for the /static route
+ await app.clickLink("/static");
+ await page.waitForSelector("#static");
+ expect(await app.getHtml("#static")).toMatch("Static");
+ expect(manifestRequests).toEqual([
+ expect.stringMatching(/\/__manifest\?version=[a-z0-9]{8}&p=%2Fstatic/),
+ ]);
+ expect(
+ await page.evaluate(() =>
+ Object.keys((window as any).__remixManifest.routes)
+ )
+ ).toEqual(["root", "routes/_index", "routes/$", "routes/static"]);
+ });
+
+ test("does not re-request for previously discovered slug routes", async ({
+ page,
+ }) => {
+ let fixture = await createFixture({
+ config: {
+ future: {
+ unstable_lazyRouteDiscovery: true,
+ },
+ },
+ files: {
+ "app/root.tsx": js`
+ import { Link, Outlet, Scripts } from "@remix-run/react";
+
+ export default function Root() {
+ return (
+
+
+
+
+ Go to /
+ Go to /a
+ Go to /b
+
+
+
+
+
+ );
+ }
+ `,
+
+ "app/routes/_index.tsx": js`
+ export default function Index() {
+ return Index ;
+ }
+ `,
+ "app/routes/$slug.tsx": js`
+ import { Link, useParams } from "@remix-run/react";
+ export default function Component() {
+ let params = useParams();
+ return Slug: {params.slug} ;
+ }
+ `,
+ },
+ });
+ let appFixture = await createAppFixture(fixture);
+ let app = new PlaywrightFixture(appFixture, page);
+
+ let manifestRequests: string[] = [];
+ page.on("request", (req) => {
+ if (req.url().includes("/__manifest")) {
+ manifestRequests.push(req.url());
+ }
+ });
+
+ await app.goto("/", true);
+ expect(await app.getHtml("#index")).toMatch("Index");
+ expect(
+ await page.evaluate(() =>
+ Object.keys((window as any).__remixManifest.routes)
+ )
+ ).toEqual(["root", "routes/_index"]);
+ expect(manifestRequests.length).toBe(0);
+
+ // Click /a which will discover via a manifest request
+ await app.clickLink("/a");
+ await page.waitForSelector("#slug");
+ expect(await app.getHtml("#slug")).toMatch("Slug: a");
+ expect(manifestRequests).toEqual([
+ expect.stringMatching(/\/__manifest\?version=[a-z0-9]{8}&p=%2Fa/),
+ ]);
+ manifestRequests = [];
+
+ // Go back home
+ await app.clickLink("/");
+ await page.waitForSelector("#index");
+ expect(manifestRequests).toEqual([]);
+
+ // Click /a again which will not re-discover
+ await app.clickLink("/a");
+ await page.waitForSelector("#slug");
+ expect(await app.getHtml("#slug")).toMatch("Slug: a");
+ expect(manifestRequests).toEqual([]);
+ manifestRequests = [];
+
+ // Click /b which will need to discover
+ await app.clickLink("/b");
+ await page.waitForSelector("#slug");
+ expect(await app.getHtml("#slug")).toMatch("Slug: b");
+ expect(manifestRequests).toEqual([
+ expect.stringMatching(/\/__manifest\?version=[a-z0-9]{8}&p=%2Fb/),
+ ]);
+ });
+
+ test("does not re-request for previously discovered splat routes", async ({
+ page,
+ }) => {
+ let fixture = await createFixture({
+ config: {
+ future: {
+ unstable_lazyRouteDiscovery: true,
+ },
+ },
+ files: {
+ "app/root.tsx": js`
+ import { Link, Outlet, Scripts } from "@remix-run/react";
+
+ export default function Root() {
+ return (
+
+
+
+
+ Go to /
+ Go to /a
+ Go to /b/c
+
+
+
+
+
+ );
+ }
+ `,
+
+ "app/routes/_index.tsx": js`
+ export default function Index() {
+ return Index ;
+ }
+ `,
+ "app/routes/$.tsx": js`
+ import { Link, useParams } from "@remix-run/react";
+ export default function Component() {
+ let params = useParams();
+ return Splat: {params["*"]} ;
+ }
+ `,
+ },
+ });
+ let appFixture = await createAppFixture(fixture);
+ let app = new PlaywrightFixture(appFixture, page);
+
+ let manifestRequests: string[] = [];
+ page.on("request", (req) => {
+ if (req.url().includes("/__manifest")) {
+ manifestRequests.push(req.url());
+ }
+ });
+
+ await app.goto("/", true);
+ expect(await app.getHtml("#index")).toMatch("Index");
+ expect(
+ await page.evaluate(() =>
+ Object.keys((window as any).__remixManifest.routes)
+ )
+ ).toEqual(["root", "routes/_index"]);
+ expect(manifestRequests.length).toBe(0);
+
+ // Click /a which will discover via a manifest request
+ await app.clickLink("/a");
+ await page.waitForSelector("#splat");
+ expect(await app.getHtml("#splat")).toMatch("Splat: a");
+ expect(manifestRequests).toEqual([
+ expect.stringMatching(/\/__manifest\?version=[a-z0-9]{8}&p=%2Fa/),
+ ]);
+ manifestRequests = [];
+
+ // Go back home
+ await app.clickLink("/");
+ await page.waitForSelector("#index");
+ expect(manifestRequests).toEqual([]);
+
+ // Click /a again which will not re-discover
+ await app.clickLink("/a");
+ await page.waitForSelector("#splat");
+ expect(await app.getHtml("#splat")).toMatch("Splat: a");
+ expect(manifestRequests).toEqual([]);
+ manifestRequests = [];
+
+ // Click /b which will need to discover
+ await app.clickLink("/b/c");
+ await page.waitForSelector("#splat");
+ expect(await app.getHtml("#splat")).toMatch("Splat: b/c");
+ expect(manifestRequests).toEqual([
+ expect.stringMatching(/\/__manifest\?version=[a-z0-9]{8}&p=%2Fb%2Fc/),
+ ]);
+ });
+
+ test("does not re-request for previously navigated 404 routes", async ({
+ page,
+ }) => {
+ let fixture = await createFixture({
+ config: {
+ future: {
+ unstable_lazyRouteDiscovery: true,
+ },
+ },
+ files: {
+ "app/root.tsx": js`
+ import { Link, Outlet, Scripts } from "@remix-run/react";
+
+ export function Layout({ children }) {
+ return (
+
+
+
+
+ Go to /
+ Go to /something
+ Go to /not/a/path
+
+ {children}
+
+
+
+ );
+ }
+ export default function Root() {
+ return ;
+ }
+
+ export function ErrorBoundary() {
+ return Error ;
+ }
+ `,
+
+ "app/routes/_index.tsx": js`
+ export default function Index() {
+ return Index ;
+ }
+ `,
+ "app/routes/$slug.tsx": js`
+ import { Link, useParams } from "@remix-run/react";
+ export default function Component() {
+ let params = useParams();
+ return Slug: {params.slug} ;
+ }
+ `,
+ },
+ });
+ let appFixture = await createAppFixture(fixture);
+ let app = new PlaywrightFixture(appFixture, page);
+
+ let manifestRequests: string[] = [];
+ page.on("request", (req) => {
+ if (req.url().includes("/__manifest")) {
+ manifestRequests.push(req.url());
+ }
+ });
+
+ await app.goto("/", true);
+ expect(await app.getHtml("#index")).toMatch("Index");
+ expect(
+ await page.evaluate(() =>
+ Object.keys((window as any).__remixManifest.routes)
+ )
+ ).toEqual(["root", "routes/_index"]);
+ expect(manifestRequests.length).toBe(0);
+
+ // Click a 404 link which will try to discover via a manifest request
+ await app.clickLink("/not/a/path");
+ await page.waitForSelector("#error");
+ expect(manifestRequests).toEqual([
+ expect.stringMatching(
+ /\/__manifest\?version=[a-z0-9]{8}&p=%2Fnot%2Fa%2Fpath/
+ ),
+ ]);
+ manifestRequests = [];
+
+ // Go to a valid slug route
+ await app.clickLink("/something");
+ await page.waitForSelector("#slug");
+ expect(manifestRequests).toEqual([
+ expect.stringMatching(/\/__manifest\?version=[a-z0-9]{8}&p=%2Fsomething/),
+ ]);
+ manifestRequests = [];
+
+ // Click the same 404 link again which will not re-discover
+ await app.clickLink("/not/a/path");
+ await page.waitForSelector("#error");
+ expect(manifestRequests).toEqual([]);
+ });
+
test("skips prefetching if the URL gets too large", async ({ page }) => {
let fixture = await createFixture({
config: {
diff --git a/integration/package.json b/integration/package.json
index cbdae1b26a2..5b6aac81978 100644
--- a/integration/package.json
+++ b/integration/package.json
@@ -14,7 +14,7 @@
"@remix-run/dev": "workspace:*",
"@remix-run/express": "workspace:*",
"@remix-run/node": "workspace:*",
- "@remix-run/router": "1.19.0",
+ "@remix-run/router": "0.0.0-experimental-5a6545bf7",
"@remix-run/server-runtime": "workspace:*",
"@types/express": "^4.17.9",
"@vanilla-extract/css": "^1.10.0",
diff --git a/packages/remix-dev/package.json b/packages/remix-dev/package.json
index bef865675f2..abbcaf0a1e9 100644
--- a/packages/remix-dev/package.json
+++ b/packages/remix-dev/package.json
@@ -32,7 +32,7 @@
"@mdx-js/mdx": "^2.3.0",
"@npmcli/package-json": "^4.0.1",
"@remix-run/node": "workspace:*",
- "@remix-run/router": "1.19.0",
+ "@remix-run/router": "0.0.0-experimental-5a6545bf7",
"@remix-run/server-runtime": "workspace:*",
"@types/mdx": "^2.0.5",
"@vanilla-extract/integration": "^6.2.0",
diff --git a/packages/remix-react/browser.tsx b/packages/remix-react/browser.tsx
index c0014b1c1e1..b7b65cb6bf9 100644
--- a/packages/remix-react/browser.tsx
+++ b/packages/remix-react/browser.tsx
@@ -20,7 +20,10 @@ import {
getSingleFetchDataStrategy,
} from "./single-fetch";
import invariant from "./invariant";
-import { initFogOfWar, useFogOFWarDiscovery } from "./fog-of-war";
+import {
+ getPatchRoutesOnNavigationFunction,
+ useFogOFWarDiscovery,
+} from "./fog-of-war";
/* eslint-disable prefer-let/prefer-let */
declare global {
@@ -305,14 +308,6 @@ export function RemixBrowser(_props: RemixBrowserProps): ReactElement {
}
}
- let { enabled: isFogOfWarEnabled, patchRoutesOnMiss } = initFogOfWar(
- window.__remixManifest,
- window.__remixRouteModules,
- window.__remixContext.future,
- window.__remixContext.isSpaMode,
- window.__remixContext.basename
- );
-
// We don't use createBrowserRouter here because we need fine-grained control
// over initialization to support synchronous `clientLoader` flows.
router = createRouter({
@@ -337,9 +332,13 @@ export function RemixBrowser(_props: RemixBrowserProps): ReactElement {
window.__remixRouteModules
)
: undefined,
- ...(isFogOfWarEnabled
- ? { unstable_patchRoutesOnMiss: patchRoutesOnMiss }
- : {}),
+ unstable_patchRoutesOnNavigation: getPatchRoutesOnNavigationFunction(
+ window.__remixManifest,
+ window.__remixRouteModules,
+ window.__remixContext.future,
+ window.__remixContext.isSpaMode,
+ window.__remixContext.basename
+ ),
});
// We can call initialize() immediately if the router doesn't have any
diff --git a/packages/remix-react/fog-of-war.ts b/packages/remix-react/fog-of-war.ts
index d2fd22ecdbb..033d4624a09 100644
--- a/packages/remix-react/fog-of-war.ts
+++ b/packages/remix-react/fog-of-war.ts
@@ -1,7 +1,7 @@
import type { Router } from "@remix-run/router";
import { matchRoutes } from "@remix-run/router";
import * as React from "react";
-import type { unstable_PatchRoutesOnMissFunction } from "react-router";
+import type { unstable_PatchRoutesOnNavigationFunction } from "react-router";
import type { AssetsManifest, FutureConfig } from "./entry";
import type { RouteModules } from "./routeModules";
@@ -13,23 +13,18 @@ declare global {
}
}
-type FogOfWarInfo = {
- // Currently rendered links that may need prefetching
- nextPaths: Set;
- // Paths we know the client can already match, so no need to perform client-side
- // matching or prefetching for them. Just an optimization to avoid re-matching
- // on a larger and larger route tree over time
- knownGoodPaths: Set;
- // Routes the server was unable to match - don't ask for them again
- known404Paths: Set;
-};
+// Currently rendered links that may need prefetching
+const nextPaths = new Set();
+
+// FIFO queue of previously discovered routes to prevent re-calling on
+// subsequent navigations to the same path
+const discoveredPathsMaxSize = 1000;
+const discoveredPaths = new Set();
// 7.5k to come in under the ~8k limit for most browsers
// https://stackoverflow.com/a/417184
const URL_LIMIT = 7680;
-let fogOfWar: FogOfWarInfo | null = null;
-
export function isFogOfWarEnabled(future: FutureConfig, isSpaMode: boolean) {
return future.unstable_lazyRouteDiscovery === true && !isSpaMode;
}
@@ -69,46 +64,29 @@ export function getPartialManifest(manifest: AssetsManifest, router: Router) {
};
}
-export function initFogOfWar(
+export function getPatchRoutesOnNavigationFunction(
manifest: AssetsManifest,
routeModules: RouteModules,
future: FutureConfig,
isSpaMode: boolean,
basename: string | undefined
-): {
- enabled: boolean;
- patchRoutesOnMiss?: unstable_PatchRoutesOnMissFunction;
-} {
+): unstable_PatchRoutesOnNavigationFunction | undefined {
if (!isFogOfWarEnabled(future, isSpaMode)) {
- return { enabled: false };
+ return undefined;
}
-
- fogOfWar = {
- nextPaths: new Set(),
- knownGoodPaths: new Set(),
- known404Paths: new Set(),
- };
-
- return {
- enabled: true,
- patchRoutesOnMiss: async ({ path, patch }) => {
- if (
- fogOfWar!.known404Paths.has(path) ||
- fogOfWar!.knownGoodPaths.has(path)
- ) {
- return;
- }
- await fetchAndApplyManifestPatches(
- [path],
- fogOfWar!,
- manifest,
- routeModules,
- future,
- isSpaMode,
- basename,
- patch
- );
- },
+ return async ({ path, patch }) => {
+ if (discoveredPaths.has(path)) {
+ return;
+ }
+ await fetchAndApplyManifestPatches(
+ [path],
+ manifest,
+ routeModules,
+ future,
+ isSpaMode,
+ basename,
+ patch
+ );
};
}
@@ -138,16 +116,21 @@ export function useFogOFWarDiscovery(
return;
}
let url = new URL(path, window.location.origin);
- let { knownGoodPaths, known404Paths, nextPaths } = fogOfWar!;
- if (knownGoodPaths.has(url.pathname) || known404Paths.has(url.pathname)) {
- return;
+ if (!discoveredPaths.has(url.pathname)) {
+ nextPaths.add(url.pathname);
}
- nextPaths.add(url.pathname);
}
// Fetch patches for all currently rendered links
async function fetchPatches() {
- let lazyPaths = getFogOfWarPaths(fogOfWar!, router);
+ let lazyPaths = Array.from(nextPaths.keys()).filter((path) => {
+ if (discoveredPaths.has(path)) {
+ nextPaths.delete(path);
+ return false;
+ }
+ return true;
+ });
+
if (lazyPaths.length === 0) {
return;
}
@@ -155,7 +138,6 @@ export function useFogOFWarDiscovery(
try {
await fetchAndApplyManifestPatches(
lazyPaths,
- fogOfWar!,
manifest,
routeModules,
future,
@@ -218,26 +200,8 @@ export function useFogOFWarDiscovery(
}, [future, isSpaMode, manifest, routeModules, router]);
}
-function getFogOfWarPaths(fogOfWar: FogOfWarInfo, router: Router) {
- let { knownGoodPaths, known404Paths, nextPaths } = fogOfWar;
- return Array.from(nextPaths.keys()).filter((path) => {
- if (knownGoodPaths.has(path)) {
- nextPaths.delete(path);
- return false;
- }
-
- if (known404Paths.has(path)) {
- nextPaths.delete(path);
- return false;
- }
-
- return true;
- });
-}
-
export async function fetchAndApplyManifestPatches(
paths: string[],
- _fogOfWar: FogOfWarInfo,
manifest: AssetsManifest,
routeModules: RouteModules,
future: FutureConfig,
@@ -245,7 +209,6 @@ export async function fetchAndApplyManifestPatches(
basename: string | undefined,
patchRoutes: Router["patchRoutes"]
): Promise {
- let { nextPaths, knownGoodPaths, known404Paths } = _fogOfWar;
let manifestPath = `${basename ?? "/"}/__manifest`.replace(/\/+/g, "/");
let url = new URL(manifestPath, window.location.origin);
url.searchParams.set("version", manifest.version);
@@ -267,16 +230,11 @@ export async function fetchAndApplyManifestPatches(
throw new Error(await res.text());
}
- let data = (await res.json()) as {
- notFoundPaths: string[];
- patches: AssetsManifest["routes"];
- };
-
- // Capture this before we apply the patches to the manifest
- let knownRoutes = new Set(Object.keys(manifest.routes));
+ let serverPatches = (await res.json()) as AssetsManifest["routes"];
// Patch routes we don't know about yet into the manifest
- let patches: AssetsManifest["routes"] = Object.values(data.patches).reduce(
+ let knownRoutes = new Set(Object.keys(manifest.routes));
+ let patches: AssetsManifest["routes"] = Object.values(serverPatches).reduce(
(acc, route) =>
!knownRoutes.has(route.id)
? Object.assign(acc, { [route.id]: route })
@@ -285,11 +243,8 @@ export async function fetchAndApplyManifestPatches(
);
Object.assign(manifest.routes, patches);
- // Track legit 404s so we don't try to fetch them again
- data.notFoundPaths.forEach((p) => known404Paths.add(p));
-
- // Track matched paths so we don't have to fetch them again
- paths.forEach((p) => knownGoodPaths.add(p));
+ // Track discovered paths so we don't have to fetch them again
+ paths.forEach((p) => addToFifoQueue(p, discoveredPaths));
// Identify all parentIds for which we have new children to add and patch
// in their new children
@@ -314,6 +269,14 @@ export async function fetchAndApplyManifestPatches(
);
}
+function addToFifoQueue(path: string, queue: Set) {
+ if (queue.size >= discoveredPathsMaxSize) {
+ let first = queue.values().next().value;
+ queue.delete(first);
+ }
+ queue.add(path);
+}
+
// Thanks Josh!
// https://www.joshwcomeau.com/snippets/javascript/debounce/
function debounce(callback: (...args: unknown[]) => unknown, wait: number) {
diff --git a/packages/remix-react/package.json b/packages/remix-react/package.json
index c502a8f928c..8ae187a55f7 100644
--- a/packages/remix-react/package.json
+++ b/packages/remix-react/package.json
@@ -19,10 +19,10 @@
"tsc": "tsc"
},
"dependencies": {
- "@remix-run/router": "1.19.0",
+ "@remix-run/router": "0.0.0-experimental-5a6545bf7",
"@remix-run/server-runtime": "workspace:*",
- "react-router": "6.26.0",
- "react-router-dom": "6.26.0",
+ "react-router": "0.0.0-experimental-5a6545bf7",
+ "react-router-dom": "0.0.0-experimental-5a6545bf7",
"turbo-stream": "2.3.0"
},
"devDependencies": {
diff --git a/packages/remix-server-runtime/package.json b/packages/remix-server-runtime/package.json
index ebe4313bc27..07ceb6156f0 100644
--- a/packages/remix-server-runtime/package.json
+++ b/packages/remix-server-runtime/package.json
@@ -19,7 +19,7 @@
"tsc": "tsc"
},
"dependencies": {
- "@remix-run/router": "1.19.0",
+ "@remix-run/router": "0.0.0-experimental-5a6545bf7",
"@types/cookie": "^0.6.0",
"@web3-storage/multipart-parser": "^1.0.0",
"cookie": "^0.6.0",
diff --git a/packages/remix-server-runtime/server.ts b/packages/remix-server-runtime/server.ts
index 6b9a724283d..a0aadba33bb 100644
--- a/packages/remix-server-runtime/server.ts
+++ b/packages/remix-server-runtime/server.ts
@@ -290,10 +290,7 @@ async function handleManifestRequest(
routes: ServerRoute[],
url: URL
) {
- let data: {
- patches: Record;
- notFoundPaths: string[];
- } = { patches: {}, notFoundPaths: [] };
+ let patches: Record = {};
if (url.searchParams.has("p")) {
for (let path of url.searchParams.getAll("p")) {
@@ -301,14 +298,12 @@ async function handleManifestRequest(
if (matches) {
for (let match of matches) {
let routeId = match.route.id;
- data.patches[routeId] = build.assets.routes[routeId];
+ patches[routeId] = build.assets.routes[routeId];
}
- } else {
- data.notFoundPaths.push(path);
}
}
- return json(data, {
+ return json(patches, {
headers: {
"Cache-Control": "public, max-age=31536000, immutable",
},
diff --git a/packages/remix-testing/package.json b/packages/remix-testing/package.json
index 4e5ff7e107c..a3df6276c4f 100644
--- a/packages/remix-testing/package.json
+++ b/packages/remix-testing/package.json
@@ -21,8 +21,8 @@
"dependencies": {
"@remix-run/node": "workspace:*",
"@remix-run/react": "workspace:*",
- "@remix-run/router": "1.19.0",
- "react-router-dom": "6.26.0"
+ "@remix-run/router": "0.0.0-experimental-5a6545bf7",
+ "react-router-dom": "0.0.0-experimental-5a6545bf7"
},
"devDependencies": {
"@remix-run/server-runtime": "workspace:*",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 278822b9086..bf410d94482 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -323,8 +323,8 @@ importers:
specifier: workspace:*
version: link:../packages/remix-node
'@remix-run/router':
- specifier: 1.19.0
- version: 1.19.0
+ specifier: 0.0.0-experimental-5a6545bf7
+ version: 0.0.0-experimental-5a6545bf7
'@remix-run/server-runtime':
specifier: workspace:*
version: link:../packages/remix-server-runtime
@@ -871,8 +871,8 @@ importers:
specifier: ^2.11.1
version: link:../remix-react
'@remix-run/router':
- specifier: 1.19.0
- version: 1.19.0
+ specifier: 0.0.0-experimental-5a6545bf7
+ version: 0.0.0-experimental-5a6545bf7
'@remix-run/server-runtime':
specifier: workspace:*
version: link:../remix-server-runtime
@@ -1217,17 +1217,17 @@ importers:
packages/remix-react:
dependencies:
'@remix-run/router':
- specifier: 1.19.0
- version: 1.19.0
+ specifier: 0.0.0-experimental-5a6545bf7
+ version: 0.0.0-experimental-5a6545bf7
'@remix-run/server-runtime':
specifier: workspace:*
version: link:../remix-server-runtime
react-router:
- specifier: 6.26.0
- version: 6.26.0(react@18.2.0)
+ specifier: 0.0.0-experimental-5a6545bf7
+ version: 0.0.0-experimental-5a6545bf7(react@18.2.0)
react-router-dom:
- specifier: 6.26.0
- version: 6.26.0(react-dom@18.2.0)(react@18.2.0)
+ specifier: 0.0.0-experimental-5a6545bf7
+ version: 0.0.0-experimental-5a6545bf7(react-dom@18.2.0)(react@18.2.0)
turbo-stream:
specifier: 2.3.0
version: 2.3.0
@@ -1303,8 +1303,8 @@ importers:
packages/remix-server-runtime:
dependencies:
'@remix-run/router':
- specifier: 1.19.0
- version: 1.19.0
+ specifier: 0.0.0-experimental-5a6545bf7
+ version: 0.0.0-experimental-5a6545bf7
'@types/cookie':
specifier: ^0.6.0
version: 0.6.0
@@ -1340,11 +1340,11 @@ importers:
specifier: workspace:*
version: link:../remix-react
'@remix-run/router':
- specifier: 1.19.0
- version: 1.19.0
+ specifier: 0.0.0-experimental-5a6545bf7
+ version: 0.0.0-experimental-5a6545bf7
react-router-dom:
- specifier: 6.26.0
- version: 6.26.0(react-dom@18.2.0)(react@18.2.0)
+ specifier: 0.0.0-experimental-5a6545bf7
+ version: 0.0.0-experimental-5a6545bf7(react-dom@18.2.0)(react@18.2.0)
devDependencies:
'@remix-run/server-runtime':
specifier: workspace:*
@@ -4201,8 +4201,8 @@ packages:
- encoding
dev: false
- /@remix-run/router@1.19.0:
- resolution: {integrity: sha512-zDICCLKEwbVYTS6TjYaWtHXxkdoUvD/QXvyVZjGCsWz5vyH7aFeONlPffPdW+Y/t6KT0MgXb2Mfjun9YpWN1dA==}
+ /@remix-run/router@0.0.0-experimental-5a6545bf7:
+ resolution: {integrity: sha512-xsFyd1dMF1kRAVwUWas7iYjhBL0z7//dQ8bVoQ3kXfgWgN7A/WX2M74PrYfa1Qe3xfgvw8h1yjbHRBvM7FA8QA==}
engines: {node: '>=14.0.0'}
dev: false
@@ -12786,26 +12786,26 @@ packages:
engines: {node: '>=0.10.0'}
dev: false
- /react-router-dom@6.26.0(react-dom@18.2.0)(react@18.2.0):
- resolution: {integrity: sha512-RRGUIiDtLrkX3uYcFiCIxKFWMcWQGMojpYZfcstc63A1+sSnVgILGIm9gNUA6na3Fm1QuPGSBQH2EMbAZOnMsQ==}
+ /react-router-dom@0.0.0-experimental-5a6545bf7(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-fidHtQFuYr6KW2KwXfXrRQFY7jqmJba3h9CY+y7KGHNtt7UxG3tJh4hpm6zhfvHMMX9ONWtNkTYIHjazDh2JBg==}
engines: {node: '>=14.0.0'}
peerDependencies:
react: '>=16.8'
react-dom: '>=16.8'
dependencies:
- '@remix-run/router': 1.19.0
+ '@remix-run/router': 0.0.0-experimental-5a6545bf7
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
- react-router: 6.26.0(react@18.2.0)
+ react-router: 0.0.0-experimental-5a6545bf7(react@18.2.0)
dev: false
- /react-router@6.26.0(react@18.2.0):
- resolution: {integrity: sha512-wVQq0/iFYd3iZ9H2l3N3k4PL8EEHcb0XlU2Na8nEwmiXgIUElEH6gaJDtUQxJ+JFzmIXaQjfdpcGWaM6IoQGxg==}
+ /react-router@0.0.0-experimental-5a6545bf7(react@18.2.0):
+ resolution: {integrity: sha512-88Ft7yZN0q99d+s4RMV6kaXWLjMMHvGZuOIcOXJ+yVgLOQXXiq8xFBD40D4pyaHYtuo7tR+NK9ti8rhhFx1poA==}
engines: {node: '>=14.0.0'}
peerDependencies:
react: '>=16.8'
dependencies:
- '@remix-run/router': 1.19.0
+ '@remix-run/router': 0.0.0-experimental-5a6545bf7
react: 18.2.0
dev: false