Skip to content

fix(vite-plugin-react-router): fix prerendering by not clobbering SSR bundle entries#620

Merged
serhalp merged 8 commits intomainfrom
serhalp/frb-2082-bug-rollupoptionsinput-overwrite-breaks-react-router
Jan 19, 2026
Merged

fix(vite-plugin-react-router): fix prerendering by not clobbering SSR bundle entries#620
serhalp merged 8 commits intomainfrom
serhalp/frb-2082-bug-rollupoptionsinput-overwrite-breaks-react-router

Conversation

@serhalp
Copy link
Member

@serhalp serhalp commented Jan 13, 2026

Description

@netlify/vite-plugin-react-router was overwriting the entire config.build.rollupOptions.input value during SSR build, which removed entries set by other plugins. This was intentional, because we believed RR7's original SSR bundle entry wasn't needed (our entry for our generated Netlify Function references it). It turns out that when opting in to React Router 7 framework mode prerendering, this bundle output is required. Some details can be found here: remix-run/react-router#13226 (comment).

This PR fixes the issue by preserving existing input entries and merging them with Netlify's entry.

The repo already skipped e2e tests for prendering. This PR unskips them and they now just work 🎉.

Related Tickets & Documents

QA Instructions, Screenshots, Recordings

Reproduction Steps

  1. Create a new project using the official Netlify template:
npx create-react-router@latest --template netlify/react-router-template
cd ./your-project
npm install
npx netlify init
  1. Replace react-router.config.ts with:
import type { Config } from "@react-router/dev/config";

export default {
  ssr: true,
  future: {
    v8_middleware: true,
  },
  async prerender() {
    return ["/"];
  },
} satisfies Config;
  1. Run the build:
npx netlify deploy # or even just `npm run build`

Before this fix

Build fails with:

✗ Build failed in 283ms
[react-router] Server build file not found in manifest

After this fix

Build succeeds with prerender working:

build/server/server.js                         0.35 kB
build/server/assets/server-build-lv_U4l46.js  14.57 kB   ← preserved

Prerender (html): / -> build/client/index.html
✓ built in 292ms

nahyeongjin1 and others added 3 commits January 13, 2026 11:33
- 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.
- Extract a function that thoroughly handles the rollup input merging complexity, with its own coverage
- Simplify the plugin's `config` hook to leverage the hook's "just return a deep partial update
  object" behaviour instead of mutating the passed-in config
@netlify
Copy link

netlify bot commented Jan 13, 2026

Deploy Preview for remix-edge ready!

Name Link
🔨 Latest commit bd3f0ec
🔍 Latest deploy log https://app.netlify.com/projects/remix-edge/deploys/696bb0cf6df44900070da718
😎 Deploy Preview https://deploy-preview-620--remix-edge.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link

netlify bot commented Jan 13, 2026

Deploy Preview for remix-serverless ready!

Name Link
🔨 Latest commit bd3f0ec
🔍 Latest deploy log https://app.netlify.com/projects/remix-serverless/deploys/696bb0cf9f85d70008a686fb
😎 Deploy Preview https://deploy-preview-620--remix-serverless.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions github-actions bot added the type: bug code to address defects in shipped code label Jan 13, 2026
@serhalp serhalp marked this pull request as ready for review January 14, 2026 01:16
@serhalp serhalp requested a review from a team as a code owner January 14, 2026 01:16
Comment on lines +30 to +33
if (typeof input === 'string') {
// For a single string input, the default entry name is 'index'
return { index: input }
}
Copy link
Contributor

@pieh pieh Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried vanilla rollup project with config like so:

export default {
  input: "src/main.js",
  output: {
    entryFileNames: "[name].js",
    format: "cjs",
  },
};

and using npx rollup -c -d dist result in dist/main.js being produced, not dist/index.js

... but maybe vite (or even react-router) does something here and not just rollup 🤷

But also this might be path that is never actually used in practice in react router projects, so not sure if it matters if this is not fully right 🤷

Copy link
Member Author

@serhalp serhalp Jan 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great catch. You're absolutely right. I was misled by files that happened to end with /index.js 🤦🏼. Fixed in bd3f0ec.

pieh
pieh previously approved these changes Jan 14, 2026
Copy link
Contributor

@pieh pieh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Despite the one question - all our tests (including unskipped one) is passing, so this looks OK to me 👍

@serhalp serhalp merged commit 54851a9 into main Jan 19, 2026
17 checks passed
@serhalp serhalp deleted the serhalp/frb-2082-bug-rollupoptionsinput-overwrite-breaks-react-router branch January 19, 2026 16:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: bug code to address defects in shipped code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] rollupOptions.input overwrite breaks React Router prerender

4 participants