From d3e318be3fd15e074b3d1f683e6791353a24a00c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=82=98=ED=98=95=EC=A7=84?= Date: Mon, 29 Dec 2025 13:57:11 +0900 Subject: [PATCH 1/2] fix: preserve existing rollup input entries during SSR build The plugin was overwriting the entire rollup input config, which removed entries set by other plugins (e.g., react-router's prerender server-build). Now it merges existing input entries with the Netlify function handler entry. --- packages/vite-plugin-react-router/src/plugin.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/vite-plugin-react-router/src/plugin.ts b/packages/vite-plugin-react-router/src/plugin.ts index 7a18e22d4..74f6b49fa 100644 --- a/packages/vite-plugin-react-router/src/plugin.ts +++ b/packages/vite-plugin-react-router/src/plugin.ts @@ -109,7 +109,23 @@ export function netlifyPlugin(options: NetlifyPluginOptions = {}): Plugin { // Netlify function handler via a virtual module) config.build ??= {} config.build.rollupOptions ??= {} + // Preserve any existing rollup input entries (e.g., from react-router's prerender) + // and merge them with our Netlify function handler entry + const existingInput = config.build.rollupOptions.input + let mergedInput: Record = {} + + if (typeof existingInput === 'string') { + mergedInput['default'] = existingInput + } else if (Array.isArray(existingInput)) { + existingInput.forEach((entry, i) => { + mergedInput[`entry-${i}`] = entry + }) + } else if (existingInput && typeof existingInput === 'object') { + mergedInput = { ...existingInput } + } + config.build.rollupOptions.input = { + ...mergedInput, [FUNCTION_HANDLER_CHUNK]: FUNCTION_HANDLER_MODULE_ID, } config.build.rollupOptions.output ??= {} From 510129f4cb31ad47470627ad700f877826bb6678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=82=98=ED=98=95=EC=A7=84?= Date: Wed, 7 Jan 2026 19:10:04 +0900 Subject: [PATCH 2/2] test: enable prerender e2e tests after rollupOptions.input fix - Enable previously skipped prerender tests for both serverless and edge sites. - The tests were disabled due to React Router issue #13226, but now work correctly after the rollupOptions.input merge fix in plugin.ts. --- .../react-router-edge-site/react-router.config.ts | 7 ++++--- .../react-router.config.ts | 7 ++++--- tests/e2e/react-router-user-journeys.spec.ts | 12 ++++++------ 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/tests/e2e/fixtures/react-router-edge-site/react-router.config.ts b/tests/e2e/fixtures/react-router-edge-site/react-router.config.ts index 23bad8817..755ea7da9 100644 --- a/tests/e2e/fixtures/react-router-edge-site/react-router.config.ts +++ b/tests/e2e/fixtures/react-router-edge-site/react-router.config.ts @@ -4,7 +4,8 @@ export default { // Config options... // Server-side render by default, to enable SPA mode set this to `false` ssr: true, - // TODO(serhalp) Revisit this if RR team changes their minds: - // https://github.com/remix-run/react-router/issues/13226#issuecomment-2776672461. - // prerender: ['/prerendered'], + // Previously disabled due to https://github.com/remix-run/react-router/issues/13226#issuecomment-2776672461. + // Now enabled after fixing rollupOptions.input merge in plugin.ts to preserve existing entries + // including 'virtual:react-router/server-build'. + prerender: ['/prerendered'], } satisfies Config diff --git a/tests/e2e/fixtures/react-router-serverless-site/react-router.config.ts b/tests/e2e/fixtures/react-router-serverless-site/react-router.config.ts index 23bad8817..755ea7da9 100644 --- a/tests/e2e/fixtures/react-router-serverless-site/react-router.config.ts +++ b/tests/e2e/fixtures/react-router-serverless-site/react-router.config.ts @@ -4,7 +4,8 @@ export default { // Config options... // Server-side render by default, to enable SPA mode set this to `false` ssr: true, - // TODO(serhalp) Revisit this if RR team changes their minds: - // https://github.com/remix-run/react-router/issues/13226#issuecomment-2776672461. - // prerender: ['/prerendered'], + // Previously disabled due to https://github.com/remix-run/react-router/issues/13226#issuecomment-2776672461. + // Now enabled after fixing rollupOptions.input merge in plugin.ts to preserve existing entries + // including 'virtual:react-router/server-build'. + prerender: ['/prerendered'], } satisfies Config diff --git a/tests/e2e/react-router-user-journeys.spec.ts b/tests/e2e/react-router-user-journeys.spec.ts index 7c9418e40..6332bd289 100644 --- a/tests/e2e/react-router-user-journeys.spec.ts +++ b/tests/e2e/react-router-user-journeys.spec.ts @@ -33,9 +33,9 @@ test.describe('React Router user journeys', () => { expect(response?.headers()['cache-status']).toMatch(CACHE_STATUS_SERVED_FROM_EDGE) }) - // TODO(serhalp) Revisit this if RR team changes their minds: - // https://github.com/remix-run/react-router/issues/13226#issuecomment-2776672461. - test.skip('serves a response from the CDN (without compute) for a pre-rendered route', async ({ + // Previously skipped due to https://github.com/remix-run/react-router/issues/13226#issuecomment-2776672461. + // Now enabled after fixing rollupOptions.input merge in plugin.ts to preserve existing entries. + test('serves a response from the CDN (without compute) for a pre-rendered route', async ({ page, reactRouterServerlessSite, }) => { @@ -177,9 +177,9 @@ test.describe('React Router user journeys', () => { expect(response?.headers()['cache-status']).toMatch(CACHE_STATUS_SERVED_FROM_EDGE) }) - // TODO(serhalp) Revisit this if RR team changes their minds: - // https://github.com/remix-run/react-router/issues/13226#issuecomment-2776672461. - test.skip('serves a response from the CDN (without compute) for a pre-rendered route', async ({ + // Previously skipped due to https://github.com/remix-run/react-router/issues/13226#issuecomment-2776672461. + // Now enabled after fixing rollupOptions.input merge in plugin.ts to preserve existing entries. + test('serves a response from the CDN (without compute) for a pre-rendered route', async ({ page, reactRouterEdgeSite, }) => {