Skip to content

fix(vite): do not force node condition in non-Node environments#14936

Open
Kanevry wants to merge 2 commits intoremix-run:devfrom
Kanevry:fix/vite-node-condition
Open

fix(vite): do not force node condition in non-Node environments#14936
Kanevry wants to merge 2 commits intoremix-run:devfrom
Kanevry:fix/vite-node-condition

Conversation

@Kanevry
Copy link
Copy Markdown

@Kanevry Kanevry commented Mar 26, 2026

What

Stop unconditionally adding the "node" condition to externalConditions for all SSR environments when v8_viteEnvironmentApi is enabled. Instead, set it per-environment in the configEnvironment hook so that non-Node runtimes are not forced to resolve Node.js-specific package exports.

Fixes #14730

Why

The Vite plugin hardcodes let defaultExternalConditions = ["node"] in getBaseServerOptions() and applies it to all SSR environments. When deploying to Cloudflare Workers (or other edge runtimes), this forces Vite to resolve Node.js-specific exports from packages, causing builds to fail because these runtimes cannot import builtins like http and https.

The "node" condition was deliberately introduced in #13871 because Vite does not export defaultExternalConditions. However, it should not be applied to non-Node environments.

How

Two changes in packages/react-router-dev/vite/plugin.ts:

  1. getBaseServerOptions(): When v8_viteEnvironmentApi is enabled, externalConditions no longer includes "node". This mirrors how resolve.external is already conditional on v8_viteEnvironmentApi.

  2. configEnvironment hook: "node" is added to externalConditions only when options.resolve?.noExternal !== true. This uses the same noExternal signal already checked in this hook for resolve.external, set by @cloudflare/vite-plugin for non-Node runtimes.

Behavior by scenario:

  • Node.js (v8_viteEnvironmentApi=true): "node" added via configEnvironment — same as before
  • Cloudflare Workers (v8_viteEnvironmentApi=true, noExternal: true): "node" NOT added — fix
  • Legacy (v8_viteEnvironmentApi=false): unchanged

Test Plan

  • Full test suite: 120/120 suites, 2509/2509 tests pass
  • pnpm build — all packages build successfully
  • pnpm typecheck — zero type errors
  • pnpm lint — zero new errors
  • Code path analysis confirms correct behavior for Node.js, Cloudflare Workers, and legacy modes

…x-run#14730)

When v8_viteEnvironmentApi is enabled, the node resolve condition was
unconditionally added to externalConditions for all SSR environments
via getBaseServerOptions(). This caused builds to break for non-Node
runtimes like Cloudflare Workers, which cannot import Node builtins.

The fix:
1. getBaseServerOptions(): when v8_viteEnvironmentApi is enabled,
   externalConditions no longer includes node.
2. configEnvironment hook: node is only added to externalConditions
   when options.resolve?.noExternal !== true. The noExternal signal
   is already used by @cloudflare/vite-plugin.

Node.js environments are unaffected (noExternal is not set).
Legacy mode (v8_viteEnvironmentApi=false) is also unaffected.

Fixes remix-run#14730
@remix-cla-bot
Copy link
Copy Markdown
Contributor

remix-cla-bot bot commented Mar 26, 2026

Hi @Kanevry,

Welcome, and thank you for contributing to React Router!

Before we consider your pull request, we ask that you sign our Contributor License Agreement (CLA). We require this only once.

You may review the CLA and sign it by adding your name to contributors.yml.

Once the CLA is signed, the CLA Signed label will be added to the pull request.

If you have already signed the CLA and received this response in error, or if you have any questions, please contact us at [email protected].

Thanks!

- The Remix team

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 26, 2026

🦋 Changeset detected

Latest commit: ac1029e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
@react-router/dev Patch
@react-router/fs-routes Patch
@react-router/remix-routes-option-adapter Patch
create-react-router Patch
react-router Patch
react-router-dom Patch
@react-router/architect Patch
@react-router/cloudflare Patch
@react-router/express Patch
@react-router/node Patch
@react-router/serve Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@remix-cla-bot
Copy link
Copy Markdown
Contributor

remix-cla-bot bot commented Mar 26, 2026

Thank you for signing the Contributor License Agreement. Let's get this merged! 🥳

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant