From 6a652d51f46cf94e17e1ed7519f47ef746129943 Mon Sep 17 00:00:00 2001 From: korkt-kim Date: Wed, 21 Jan 2026 13:37:32 +0900 Subject: [PATCH] fix: prerender output paths should not include basename --- .changeset/fix-prerender-basename-path.md | 5 +++ contributors.yml | 1 + integration/vite-prerender-test.ts | 42 +++++++++++++++++++++++ packages/react-router-dev/vite/plugin.ts | 9 +++-- 4 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 .changeset/fix-prerender-basename-path.md diff --git a/.changeset/fix-prerender-basename-path.md b/.changeset/fix-prerender-basename-path.md new file mode 100644 index 0000000000..2d82685a87 --- /dev/null +++ b/.changeset/fix-prerender-basename-path.md @@ -0,0 +1,5 @@ +--- +"@react-router/dev": patch +--- + +Fix prerender output paths to not include basename diff --git a/contributors.yml b/contributors.yml index 958aa1166c..dbda47a57c 100644 --- a/contributors.yml +++ b/contributors.yml @@ -230,6 +230,7 @@ - kno-raziel - knownasilya - koojaa +- korkt-kim - KostiantynPopovych - KubasuIvanSakwa - KutnerUri diff --git a/integration/vite-prerender-test.ts b/integration/vite-prerender-test.ts index db0b0cbaec..7ce67320a7 100644 --- a/integration/vite-prerender-test.ts +++ b/integration/vite-prerender-test.ts @@ -3008,5 +3008,47 @@ test.describe("Prerendering", () => { ); expect(requests).toEqual([]); }); + + test("Prerenders files in correct path with basename", async () => { + fixture = await createFixture({ + prerender: true, + files: { + "react-router.config.ts": reactRouterConfig({ + prerender: ["/", "/about"], + basename: "/base", + }), + "vite.config.ts": files["vite.config.ts"], + "app/root.tsx": js` + import { Outlet, Scripts } from "react-router"; + export function Layout({ children }) { + return ( + {children} + ); + } + export default function Root() { + return ; + } + `, + "app/routes/_index.tsx": js` + export function loader() { return "INDEX"; } + export default function Index() { return

Index

; } + `, + "app/routes/about.tsx": js` + export function loader() { return "ABOUT"; } + export default function About() { return

About

; } + `, + }, + }); + + let clientDir = path.join(fixture.projectDir, "build", "client"); + // basename should NOT create a subfolder - it's the deployment path, not build output path + expect(listAllFiles(clientDir).sort()).toEqual([ + "_root.data", + "about.data", + "about/index.html", + "favicon.ico", + "index.html", + ]); + }); }); }); diff --git a/packages/react-router-dev/vite/plugin.ts b/packages/react-router-dev/vite/plugin.ts index 5ea6f1b1f6..a1a4a4c88f 100644 --- a/packages/react-router-dev/vite/plugin.ts +++ b/packages/react-router-dev/vite/plugin.ts @@ -2934,7 +2934,7 @@ async function prerenderData( } // Write out the .data file - let outfile = path.join(clientBuildDirectory, ...normalizedPath.split("/")); + let outfile = path.join(clientBuildDirectory, ...dataRequestPath.split("/")); await mkdir(path.dirname(outfile), { recursive: true }); await writeFile(outfile, data); viteConfig.logger.info( @@ -2996,7 +2996,7 @@ async function prerenderRoute( // Write out the HTML file let outfile = path.join( clientBuildDirectory, - ...normalizedPath.split("/"), + ...prerenderPath.split("/"), "index.html", ); await mkdir(path.dirname(outfile), { recursive: true }); @@ -3032,7 +3032,10 @@ async function prerenderResourceRoute( } // Write out the resource route file - let outfile = path.join(clientBuildDirectory, ...normalizedPath.split("/")); + let outfile = path.join( + clientBuildDirectory, + ...`${prerenderPath}/`.replace(/\/\/+/g, "/").replace(/\/$/g, "").split("/") + ); await mkdir(path.dirname(outfile), { recursive: true }); await writeFile(outfile, content); viteConfig.logger.info(