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 ( + + + + + + + + + ); + } + `, + + "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 ( + + + + + + + + + ); + } + `, + + "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 ( + + + + + + + + + ); + } + `, + + "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 ( + + + + + + + + + ); + } + `, + + "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 ( + + + + + {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