diff --git a/.changeset/fix-spa-vite-preview.md b/.changeset/fix-spa-vite-preview.md new file mode 100644 index 0000000000..23c077eec1 --- /dev/null +++ b/.changeset/fix-spa-vite-preview.md @@ -0,0 +1,5 @@ +--- +"@react-router/dev": patch +--- + +fix(vite): Skip SSR middleware in preview server for SPA mode diff --git a/contributors.yml b/contributors.yml index ff24ac4b77..e8a8cd30dd 100644 --- a/contributors.yml +++ b/contributors.yml @@ -29,6 +29,7 @@ - amsal - Andarist - andreasottosson-polestar +- andreiborza - andreiduca - antonmontrezor - appden diff --git a/integration/vite-preview-test.ts b/integration/vite-preview-test.ts index 65eb1611fe..bdf23eecf8 100644 --- a/integration/vite-preview-test.ts +++ b/integration/vite-preview-test.ts @@ -314,4 +314,74 @@ test.describe("Vite preview", () => { "Product 123", ); }); + + test("serves SPA mode app with vite preview", async ({ + vitePreview, + page, + }) => { + const files: Files = async ({ port }) => ({ + "react-router.config.ts": reactRouterConfig({ + ssr: false, + v8_viteEnvironmentApi: true, + }), + "vite.config.ts": await viteConfig.basic({ + port, + templateName: "vite-6-template", + }), + "app/root.tsx": tsx` + import { Links, Meta, Outlet, Scripts } from "react-router"; + + export default function Root() { + return ( + + + + + + +
+

SPA Mode

+ +
+ + + + ); + } + `, + "app/routes/_index.tsx": tsx` + export default function IndexRoute() { + return ( +
+

Index

+

SPA Mode Enabled

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

About

+

About page in SPA mode

+
+ ); + } + `, + }); + + const { port } = await vitePreview(files, "vite-6-template"); + await page.goto(`http://localhost:${port}/`, { + waitUntil: "networkidle", + }); + + // Ensure no errors on page load (this would fail without the fix) + expect(page.errors).toEqual([]); + + await expect(page.locator("#index [data-title]")).toHaveText("Index"); + await expect(page.locator("#index [data-spa-mode]")).toHaveText( + "SPA Mode Enabled", + ); + }); }); diff --git a/packages/react-router-dev/vite/plugin.ts b/packages/react-router-dev/vite/plugin.ts index 4d11d253af..7fc5480541 100644 --- a/packages/react-router-dev/vite/plugin.ts +++ b/packages/react-router-dev/vite/plugin.ts @@ -1688,6 +1688,11 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = () => { }, configurePreviewServer(previewServer) { return () => { + // Skip SSR handling in SPA mode + if (!ctx.reactRouterConfig.ssr) { + return; + } + // Handle SSR requests in preview mode using the built server bundle previewServer.middlewares.use(async (req, res, next) => { try {