From 8ea4f63a68dd9ee3d463d5eab07ec685c305999f Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Fri, 11 Oct 2024 09:39:52 -0400 Subject: [PATCH 1/3] Fix typegen for routes with a client loader but no server loader --- .changeset/little-cooks-pull.md | 5 +++++ packages/react-router-dev/vite/plugin.ts | 5 +++-- packages/react-router/lib/types.ts | 9 +++------ 3 files changed, 11 insertions(+), 8 deletions(-) create mode 100644 .changeset/little-cooks-pull.md diff --git a/.changeset/little-cooks-pull.md b/.changeset/little-cooks-pull.md new file mode 100644 index 0000000000..9159ca5938 --- /dev/null +++ b/.changeset/little-cooks-pull.md @@ -0,0 +1,5 @@ +--- +"react-router": patch +--- + +Fix typegen for routes with a client loader but no server loader diff --git a/packages/react-router-dev/vite/plugin.ts b/packages/react-router-dev/vite/plugin.ts index 07593480a3..823c420a38 100644 --- a/packages/react-router-dev/vite/plugin.ts +++ b/packages/react-router-dev/vite/plugin.ts @@ -1897,12 +1897,13 @@ function determineStaticPrerenderRoutes( } recurse(routes); - if (isBooleanUsage && paramRoutes) { + if (isBooleanUsage && paramRoutes.length > 0) { viteConfig.logger.warn( "The following paths were not prerendered because Dynamic Param and Splat " + "routes cannot be prerendered when using `prerender:true`. You may want to " + "consider using the `prerender()` API if you wish to prerender slug and " + - "splat routes." + "splat routes.\n" + + paramRoutes.map((p) => " - " + p).join("\n") ); } diff --git a/packages/react-router/lib/types.ts b/packages/react-router/lib/types.ts index 0890c10462..9e980d2957 100644 --- a/packages/react-router/lib/types.ts +++ b/packages/react-router/lib/types.ts @@ -66,15 +66,12 @@ type _CreateLoaderData< ClientLoaderHydrate extends boolean, HasHydrateFallback > = - [HasHydrateFallback, ClientLoaderHydrate] extends [true, true] ? + [HasHydrateFallback, ClientLoaderHydrate] extends [true, true] ? IsDefined extends true ? ClientLoaderData : undefined : [IsDefined, IsDefined] extends [true, true] ? ServerLoaderData | ClientLoaderData : - IsDefined extends true ? - ClientLoaderHydrate extends true ? ClientLoaderData : - ClientLoaderData | undefined - : + IsDefined extends true ? ClientLoaderData : IsDefined extends true ? ServerLoaderData : undefined @@ -221,7 +218,7 @@ type __tests = [ CreateLoaderData<{ clientLoader: () => { a: string; b: Date; c: () => boolean }; }>, - undefined | { a: string; b: Date; c: () => boolean } + { a: string; b: Date; c: () => boolean } > >, Expect< From 325d66033d9b55dc770f4f75af12741e6db03409 Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Fri, 11 Oct 2024 09:53:39 -0400 Subject: [PATCH 2/3] Clean up warning --- packages/react-router-dev/vite/plugin.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/react-router-dev/vite/plugin.ts b/packages/react-router-dev/vite/plugin.ts index 823c420a38..2d87c13bfc 100644 --- a/packages/react-router-dev/vite/plugin.ts +++ b/packages/react-router-dev/vite/plugin.ts @@ -1899,11 +1899,11 @@ function determineStaticPrerenderRoutes( if (isBooleanUsage && paramRoutes.length > 0) { viteConfig.logger.warn( - "The following paths were not prerendered because Dynamic Param and Splat " + - "routes cannot be prerendered when using `prerender:true`. You may want to " + - "consider using the `prerender()` API if you wish to prerender slug and " + - "splat routes.\n" + - paramRoutes.map((p) => " - " + p).join("\n") + [ + "⚠️ Paths with dynamic/splat params cannot be prerendered when using `prerender: true`.", + "You may want to use the `prerender()` API to prerender the following paths:", + ...paramRoutes.map((p) => " - " + p), + ].join("\n") ); } From e6b7aadff6357e7d66c12f30eb4887e37293c94d Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Fri, 11 Oct 2024 10:06:05 -0400 Subject: [PATCH 3/3] Assert build warning during e2e test --- integration/vite-prerender-test.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/integration/vite-prerender-test.ts b/integration/vite-prerender-test.ts index 4b50eb57df..7e4e7381b6 100644 --- a/integration/vite-prerender-test.ts +++ b/integration/vite-prerender-test.ts @@ -1,5 +1,6 @@ import fs from "node:fs"; import path from "node:path"; +import { PassThrough } from "node:stream"; import { test, expect } from "@playwright/test"; import { @@ -153,7 +154,9 @@ test.describe("Prerendering", () => { }); test("Prerenders known static routes when true is specified", async () => { + let buildStdio = new PassThrough(); fixture = await createFixture({ + buildStdio, prerender: true, files: { ...files, @@ -192,6 +195,26 @@ test.describe("Prerendering", () => { `, }, }); + + let buildOutput: string; + let chunks: Buffer[] = []; + buildOutput = await new Promise((resolve, reject) => { + buildStdio.on("data", (chunk) => chunks.push(Buffer.from(chunk))); + buildStdio.on("error", (err) => reject(err)); + buildStdio.on("end", () => + resolve(Buffer.concat(chunks).toString("utf8")) + ); + }); + + expect(buildOutput).toContain( + [ + "⚠️ Paths with dynamic/splat params cannot be prerendered when using `prerender: true`.", + "You may want to use the `prerender()` API to prerender the following paths:", + " - :slug", + " - *", + ].join("\n") + ); + appFixture = await createAppFixture(fixture); let clientDir = path.join(fixture.projectDir, "build", "client");