Skip to content

fix(build): set correct resolve.conditions per Vite environment#1396

Open
james-elicx wants to merge 1 commit into
mainfrom
fix/issue-1356-import-conditions
Open

fix(build): set correct resolve.conditions per Vite environment#1396
james-elicx wants to merge 1 commit into
mainfrom
fix/issue-1356-import-conditions

Conversation

@james-elicx
Copy link
Copy Markdown
Member

Summary

Package exports maps were resolving to the wrong file in each Vite environment because vinext never set resolve.conditions on its environments — Vite fell back to its defaults, which lack react-server on RSC and edge-light/worker on workerd-targeting environments.

Closes #1356.

This is the equivalent of Next.js' webpack conditionNames configuration (see reactServerConditionNames and Next.js' test/e2e/import-conditions/).

What changed

Explicit resolve.conditions per Vite environment:

  • RSC envreact-server + server defaults (module, node, dev/prod). On workerd targets (Cloudflare / Nitro), also edge-light, workerd, worker.
  • SSR env — server defaults. On workerd targets, also edge-light, workerd, worker.
  • Client env — client defaults (module, browser, dev/prod).
  • Pages Router SSR and client envs get matching node / browser conditions.

@vitejs/plugin-rsc already sets react-server on its own rsc env config; setting it here makes the behaviour explicit and order-independent, and adds the edge runtime conditions that no other plugin contributes for vinext's rsc/ssr envs.

Test plan

  • Added tests/import-conditions.test.ts covering RSC / SSR / client conditions for App Router and Pages Router, both with and without the Cloudflare plugin (7 tests, all 7 failed on main and pass on this branch).
  • pnpm test tests/import-conditions.test.ts
  • pnpm test tests/build-optimization.test.ts — 75 passing (no regressions in env config)
  • pnpm test tests/optimize-imports.test.ts tests/app-router.test.ts tests/pages-router.test.ts — 568 passing
  • pnpm run check — clean

Package `exports` maps were resolving to the wrong file in each Vite
environment because vinext never set `resolve.conditions` on its
environments — Vite fell back to its defaults, which lack `react-server`
on RSC and `edge-light`/`worker` on workerd-targeting environments.

Set explicit conditions per environment, mirroring Next.js webpack:

- RSC env: `react-server` + server defaults (+ edge conditions on workerd)
- SSR env: server defaults (`module`, `node`, ...) (+ edge conditions on workerd)
- Client env: client defaults (`module`, `browser`, ...)

Closes #1356.
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 20, 2026

Open in StackBlitz

npm i https://pkg.pr.new/vinext@1396

commit: dde9665

@github-actions
Copy link
Copy Markdown

Example Preview Production Original
app-router-cloudflare preview production
pages-router-cloudflare preview production
app-router-playground preview production original
realworld-api-rest preview production
nextra-docs-template preview production
benchmarks preview production
hackernews preview production original
web preview production

@james-elicx
Copy link
Copy Markdown
Member Author

/bigbonk review

Copy link
Copy Markdown
Contributor

@ask-bonk ask-bonk Bot left a comment

Choose a reason for hiding this comment

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

Review: fix(build): set correct resolve.conditions per Vite environment

Reviewed the implementation and test coverage. This is a clean, well-targeted fix for a real resolution gap.

What's correct

The core approach is right: since Vite's resolve.conditions for environment configs does full replacement (not merge), explicitly setting the conditions per environment is the only way to ensure the correct export map entries are resolved. The PR correctly uses Vite's "development|production" sentinel value (matching defaultClientConditions / defaultServerConditions), which Vite internally resolves to the appropriate condition based on build mode.

The condition lists match Next.js semantics:

  • RSC: react-server + server defaults (and edge conditions when targeting workerd)
  • SSR: server defaults (and edge conditions when targeting workerd)
  • Client: browser defaults

The restructuring of the resolve object — pulling conditions up to the resolve level while spreading external/noExternal conditionally — preserves the existing behavior while adding the new conditions cleanly.

Test quality

The tests are well-structured: each test creates a fresh temp directory with proper app/ or pages/ structure, creates a fresh vinext() plugin instance (avoiding shared state), and properly cleans up. The NODE_ENV save/restore in beforeEach/afterEach handles the config hook's side effect correctly. Good coverage of all five environment × platform combinations.

Observations (non-blocking)

  1. Pages Router on Cloudflare (line 1875): This branch only defines a client environment — no ssr environment is emitted. The SSR for Pages Router on Cloudflare runs in the Cloudflare plugin's own worker environment, which sets its own edge-light/workerd/worker conditions. So the omission is correct, but a brief comment explaining why there's no SSR env here (and thus no SSR conditions to set) would help future readers avoid the same "wait, where are the SSR edge conditions?" question.

  2. node condition on edge SSR: When hasCloudflarePlugin is true, the SSR conditions include both node and edge-light/workerd/worker. The node condition comes from SERVER_DEFAULT_CONDITIONS. This matches Vite's defaults but is technically inaccurate for workerd (which is not a Node runtime). In practice this shouldn't cause issues — packages rarely have both node and edge-light exports that conflict — but it's worth noting as a potential future refinement. Next.js uses different conditionNames arrays for Node vs Edge runtimes and does not include node when targeting edge.

  3. No test for Pages Router on Cloudflare client conditions: The Pages Router tests cover pages/ on Node (checking SSR node and client browser), but there's no test for Pages Router + Cloudflare plugin. The implementation does set client conditions in that branch (line 1887), so a test would be nice for completeness — though the existing App Router + Cloudflare tests provide good confidence the detection logic works.

Looks good to merge.

@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk Bot commented May 20, 2026

Review posted and approved on PR #1396. Here's a summary:

Approved. The PR correctly fixes the missing resolve.conditions per Vite environment. Key points:

  • The approach is correct: Vite does full replacement (not merge) for conditions arrays, so explicit per-environment conditions are required. The "development|production" sentinel matches Vite's own defaultClientConditions/defaultServerConditions.
  • The condition lists match Next.js webpack semantics (react-server for RSC, node for SSR, browser for client, plus edge-light/workerd/worker on Cloudflare).
  • Tests are well-structured with proper isolation (fresh plugin instances, temp dirs, NODE_ENV save/restore).

I noted three non-blocking observations:

  1. A comment explaining why the Pages Router + Cloudflare branch omits SSR env conditions (Cloudflare's plugin owns that environment) would aid readability.
  2. The node condition is included alongside edge-light/worker on workerd SSR, which is technically inaccurate but harmless in practice — Next.js uses separate condition arrays for Node vs Edge.
  3. No test coverage for Pages Router + Cloudflare client conditions, though existing App Router + Cloudflare tests cover the detection logic.

github run

@james-elicx james-elicx marked this pull request as ready for review May 20, 2026 20:55
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.

Import condition resolution wrong per Vite environment (react-server, edge-light, browser)

1 participant