From 4ed3f5da97a44c3f74eb8973d66c0d918017d68f Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Wed, 8 May 2024 12:00:57 -0400 Subject: [PATCH] Minor updates --- .../react-router/lib/dom/ssr/single-fetch.tsx | 9 ++-- packages/remix-dev/vite/plugin.ts | 45 ++++++++++++------- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/packages/react-router/lib/dom/ssr/single-fetch.tsx b/packages/react-router/lib/dom/ssr/single-fetch.tsx index e6a7eaf9b0..952fd035b1 100644 --- a/packages/react-router/lib/dom/ssr/single-fetch.tsx +++ b/packages/react-router/lib/dom/ssr/single-fetch.tsx @@ -299,9 +299,12 @@ async function fetchAndDecode(url: URL, init?: RequestInit) { let decoded = await decodeViaTurboStream(res.body, window); return { status: res.status, data: decoded.value }; } catch (e) { - // Unfortunately I don't think we can get access to the response text here. - // Pre-emptively cloning seems incorrect and we can't clone after consuming - // the body via turbo-stream + // Can't clone after consuming the body via turbo-stream so we can't + // include the body here. In an ideal world we'd look for a turbo-stream + // content type here, or even X-Remix-Response but then folks can't + // statically deploy their prerendered .data files to a CDN unless they can + // tell that CDN to add special headers to those certain files - which is a + // bit restrictive. throw new Error("Unable to decode turbo-stream response"); } } diff --git a/packages/remix-dev/vite/plugin.ts b/packages/remix-dev/vite/plugin.ts index 6950ab2319..837c13412e 100644 --- a/packages/remix-dev/vite/plugin.ts +++ b/packages/remix-dev/vite/plugin.ts @@ -1174,21 +1174,37 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = (_config) => { ); } - if (!ctx.reactRouterConfig.ssr) { - await handleSpaMode( + if (ctx.reactRouterConfig.prerender != null) { + // If we have prerender routes, that takes precedence over SPA mode + // which is ssr:false and only the rot route being rendered + await handlePrerender( viteConfig, ctx.reactRouterConfig, serverBuildDirectory, clientBuildDirectory ); - } else if (ctx.reactRouterConfig.prerender != null) { - await handlePrerender( + } else if (!ctx.reactRouterConfig.ssr) { + await handleSpaMode( viteConfig, ctx.reactRouterConfig, serverBuildDirectory, clientBuildDirectory ); } + + // For both SPA mode and prerendering, we can remove the server builds + // if ssr:false is set + if (!ctx.reactRouterConfig.ssr) { + // Cleanup - we no longer need the server build assets + viteConfig.logger.info( + [ + "Removing the server build in", + colors.green(serverBuildDirectory), + "due to ssr:false", + ].join(" ") + ); + fse.removeSync(serverBuildDirectory); + } }, }, async buildEnd() { @@ -1642,10 +1658,10 @@ async function getRouteMetadata( async function getPrerenderBuildAndHandler( viteConfig: Vite.ResolvedConfig, reactRouterConfig: Awaited>, - serverBuildDirectoryPath: string + serverBuildDirectory: string ) { let serverBuildPath = path.join( - serverBuildDirectoryPath, + serverBuildDirectory, reactRouterConfig.serverBuildFile ); let build = await import(url.pathToFileURL(serverBuildPath).toString()); @@ -1661,13 +1677,13 @@ async function getPrerenderBuildAndHandler( async function handleSpaMode( viteConfig: Vite.ResolvedConfig, reactRouterConfig: Awaited>, - serverBuildDirectoryPath: string, + serverBuildDirectory: string, clientBuildDirectory: string ) { let { handler } = await getPrerenderBuildAndHandler( viteConfig, reactRouterConfig, - serverBuildDirectoryPath + serverBuildDirectory ); let request = new Request(`http://localhost${reactRouterConfig.basename}`); let response = await handler(request); @@ -1699,28 +1715,27 @@ async function handleSpaMode( colors.bold(path.relative(process.cwd(), clientBuildDirectory)) + " directory" ); - - // Cleanup - we no longer need the server build assets - fse.removeSync(serverBuildDirectoryPath); } async function handlePrerender( viteConfig: Vite.ResolvedConfig, reactRouterConfig: Awaited>, - serverBuildDirectoryPath: string, + serverBuildDirectory: string, clientBuildDirectory: string ) { let { build, handler } = await getPrerenderBuildAndHandler( viteConfig, reactRouterConfig, - serverBuildDirectoryPath + serverBuildDirectory ); let routes = createPrerenderRoutes(build.routes); let routesToPrerender = reactRouterConfig.prerender || ["/"]; let requestInit = { headers: { - "X-React-router-Prerender": "yes", + // Header that can be used in the loader to know if you're running at + // build time or runtime + "X-React-Router-Prerender": "yes", }, }; for (let path of routesToPrerender) { @@ -1737,7 +1752,6 @@ async function handlePrerender( } await prerenderRoute( handler, - routes, reactRouterConfig.basename, path, clientBuildDirectory, @@ -1781,7 +1795,6 @@ async function handlePrerender( async function prerenderRoute( handler: RequestHandler, - routes: DataRouteObject[], basename: string, prerenderPath: string, clientBuildDirectory: string,