Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Cloudflare templates break when prerendering is enabled #45

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

ariofrio
Copy link

@ariofrio ariofrio commented Dec 23, 2024

Issue Description

The Cloudflare templates fail when prerendering is enabled (#31) due to incompatibility between its custom entry point and React Router Vite plugin's prerendering assumptions.

Technical Details

  1. During prerendering, the plugin expects the entry point to be virtual:react-router/server-build
  2. Cloudflare templates use a different entry point, causing the plugin to fail
  3. The plugin sets rollupOptions.entryFileNames to serverBuildFile from react-router.config.ts, which prevents multiple entry points in rollupOptions.input

Solution

Fix prerendering in the Cloudflare templates by:

  1. Workaround for Vite plugin limitation: Forcing entryFileNames to be [name] to support multiple entry points
  2. Specifying two entry points in input:
    • index.js: matches default serverBuildFile React Router configuration
    • worker.js: matched by updated main = "./build/server/worker.js" in wrangler.toml
  3. Explicitly setting index.js as the serverBuildFile in react-router.config.ts for clarity and discoverability

Updated both cloudflare and cloudflare-d1 templates.

Proposed Long-term Fix

The React Router Vite plugin should be updated to support custom entry points for use cases like Cloudflare Workers.

Suggested Implementation

{
  input: viteUserConfig.build?.rollupOptions?.input ?? {
    [ctx.reactRouterConfig.serverBuildFile]: serverBuildId,
  },
  output: {
    entryFileNames:
      typeof viteUserConfig.build?.rollupOptions?.input === "string"
        ? ctx.reactRouterConfig.serverBuildFile
        : "[name]",
    format: ctx.reactRouterConfig.serverModuleFormat,
  },
};

I considered leaving entryFileNames as the Rollup default [name].js, but this made it harder for the developer to match the input entries in vite.config.ts to the file names in wrangler.toml and react-router.config.ts. On the other hand, this changes Rollup's defaults and should be documented. Happy to change it back to Rollup's default and change input to {index: ..., worker: ...} if the maintainers have an opinion on this.

We should probably document this feature in general anyway though.

Next Steps

  • Open PR for official support for multiple entry points in React Router Vite plugin
  • Remove the workaround of forcing entryFileNames to be [name] in the Cloudflare templates once the React Router Vite plugin is updated

@ariofrio ariofrio changed the title fix: prerendering with Cloudflare template by using separate worker entry point fix: Cloudflare Templates Break When Prerendering is Enabled Dec 23, 2024
@ariofrio ariofrio changed the title fix: Cloudflare Templates Break When Prerendering is Enabled fix: Cloudflare templates break when prerendering is enabled Dec 23, 2024
@ariofrio ariofrio changed the title fix: Cloudflare templates break when prerendering is enabled fix: Cloudflare templates break when (partial) prerendering is enabled Dec 23, 2024
@ariofrio ariofrio changed the title fix: Cloudflare templates break when (partial) prerendering is enabled fix: Cloudflare templates break when prerendering is enabled Dec 23, 2024
@supachaidev
Copy link
Contributor

The current entry.server.ts in the templates uses the renderToReadableStream function which causes the pre-rendering to output the html files with [object ReadableStream] as content.

Not sure how to make Cloudflare templates work with the react-dom/server renderToPipeableStream function instead.

So, with current Cloudflare templates, even with the fix from this PR, pre-rendering does not work.

@caprolactam
Copy link

hi @supachaidev.

I omit detailed explanations, but this is an issue caused by the conditional exports feature in Node.js and React.

The workaround is to provide workerd resolution conditions in Node.js.

NODE_OPTIONS='--conditions workerd' react-router build

If you are windows users, use cross-env.

{
"scripts": {
    "build": "cross-env NODE_OPTIONS=\"--conditions workerd\" react-router build",
  }
}

If you are using React@18, use worker instead of workerd.

NODE_OPTIONS='--conditions worker' react-router build

For code examples, refer to this repository and commit.

@supachaidev
Copy link
Contributor

hi @supachaidev.

I omit detailed explanations, but this is an issue caused by the conditional exports feature in Node.js and React.

The workaround is to provide workerd resolution conditions in Node.js.

NODE_OPTIONS='--conditions workerd' react-router build

If you are windows users, use cross-env.

{
"scripts": {
    "build": "cross-env NODE_OPTIONS=\"--conditions workerd\" react-router build",
  }
}

If you are using React@18, use worker instead of workerd.

NODE_OPTIONS='--conditions worker' react-router build

For code examples, refer to this repository and commit.

Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants