Skip to content

feat: support @vitejs/plugin-react v6 as peer#525

Merged
james-elicx merged 12 commits intocloudflare:mainfrom
hyoban:3-13-react-peer
Mar 13, 2026
Merged

feat: support @vitejs/plugin-react v6 as peer#525
james-elicx merged 12 commits intocloudflare:mainfrom
hyoban:3-13-react-peer

Conversation

@hyoban
Copy link
Copy Markdown
Contributor

@hyoban hyoban commented Mar 13, 2026

This allows users to choose whether to use v5 or v6. To avoid installing unnecessary dependencies.

This is a small braking change.

@hyoban hyoban marked this pull request as draft March 13, 2026 13:19
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Mar 13, 2026

Open in StackBlitz

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

commit: c2e108c

@hyoban hyoban marked this pull request as ready for review March 13, 2026 13:35
@james-elicx
Copy link
Copy Markdown
Collaborator

/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.

Good change overall — moving @vitejs/plugin-react from a hard dependency to a peer dependency is the right approach for letting users choose between v5 and v6. The dynamic import pattern, duplicate detection, and test coverage are solid.

I have a few comments, mostly about edge cases and one potential test reliability issue. Nothing blocking.

Comment thread packages/vinext/package.json Outdated
Comment thread packages/vinext/src/index.ts Outdated
Comment thread packages/vinext/src/index.ts
Comment thread packages/vinext/src/deploy.ts
Comment thread packages/vinext/src/index.ts
Comment thread tests/app-router.test.ts Outdated
Comment thread tests/pages-router.test.ts Outdated
Comment thread packages/vinext/src/index.ts Outdated
Comment thread packages/vinext/src/check.ts Outdated
@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk Bot commented Mar 13, 2026

Review submitted on PR #525. Here's a summary of the feedback:

Overall: Good change. Moving @vitejs/plugin-react from a hard dependency to a peer dependency with ^5.0.0 || ^6.0.0 is the right approach for letting users choose versions. The dynamic import pattern, duplicate plugin detection, and test coverage are solid.

Key comments:

  1. Test reliability issue (most important): The "does NOT auto-inject RSC plugin" test calls vinext({ appDir: tmpDir }) on an empty /tmp/ dir without node_modules. Since createRequire can't resolve @vitejs/plugin-react from /tmp/, this should throw — but it passes in CI due to vitest's module resolution hooks. Suggested fix: pass react: false since the test is about RSC, not React.

  2. Error message missing -D flag: The install error tells users to run the package manager but doesn't include -D for devDependency, inconsistent with the README instructions.

  3. Comment accuracy: The catch block comment says "Only needed if vinext ends up auto-injecting" but auto-injection is the default — suggested a clearer comment.

  4. Breaking change note: This is a breaking change for existing users who had @vitejs/plugin-react pulled in transitively. Worth noting in changelog/migration docs.

  5. Minor items: Unrelated blank line removal, consistency note on _isResolvable vs _findInNodeModules in deploy.ts, and the check.ts manual install message always listing @vitejs/plugin-rsc even for Pages Router projects.

github run

@hyoban
Copy link
Copy Markdown
Contributor Author

hyoban commented Mar 13, 2026

All resolved

@james-elicx
Copy link
Copy Markdown
Collaborator

/bigbonk re-review

1 similar comment
@james-elicx
Copy link
Copy Markdown
Collaborator

/bigbonk re-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.

Good change. Moving @vitejs/plugin-react to a peer dependency is the right call for supporting both v5 and v6 without forcing unnecessary installs. The dynamic import pattern, duplicate detection, testability injection for getMissingDeps, and the check.ts conditional output for App Router deps are all well done.

One remaining issue from the previous review that wasn't addressed, and a couple of minor items.

Comment thread tests/app-router.test.ts Outdated
Comment thread packages/vinext/package.json Outdated
Comment thread packages/vinext/src/index.ts Outdated
@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk Bot commented Mar 13, 2026

Review submitted. Here's a summary of my feedback on PR #525:

Overall: Good change. Moving @vitejs/plugin-react from a hard dependency to a peer dependency with ^5.0.0 || ^6.0.0 is the right approach.

3 comments posted:

  1. tests/app-router.test.ts:3303 — The "does NOT auto-inject RSC plugin" test still doesn't pass react: false, which was flagged in the previous review. createRequire from an empty /tmp/ directory can't resolve @vitejs/plugin-react in plain Node.js — I verified this. The test only passes because vitest patches module resolution. Posted a suggestion to add react: false, matching the sibling test at line 3280.

  2. packages/vinext/package.json:77 — The peer dependency lower bound of ^5.0.0 is very broad while the devDep pins ^5.1.4. Worth considering whether the lower bound should be tighter.

  3. packages/vinext/src/index.ts:841 — Minor note that if the dynamic import() fails with a syntax error, it surfaces as an unhandled rejection rather than a vinext-prefixed error. Consistent with the RSC plugin pattern, so not blocking.

github run

@hyoban
Copy link
Copy Markdown
Contributor Author

hyoban commented Mar 13, 2026

All resolved

@james-elicx
Copy link
Copy Markdown
Collaborator

/bigbonk re-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.

Good change overall. Moving @vitejs/plugin-react to a peer dependency is the right architectural choice for supporting v5 and v6 side by side. The implementation is clean — dynamic import pattern, duplicate detection, testability injection in getMissingDeps, and the conditional App Router deps in check.ts are all well done. CI is green.

Missing dependency in examples

The examples under examples/ (app-router-cloudflare, pages-router-cloudflare, hackernews, etc.) don't list @vitejs/plugin-react as a dependency. Since it was removed from vinext's dependencies and moved to peerDependencies, it's no longer installed transitively for consumers.

I verified that createRequire from the example directory fails:

$ node -e "require('module').createRequire('.../examples/app-router-cloudflare/package.json').resolve('@vitejs/plugin-react')"
// throws MODULE_NOT_FOUND

The monorepo CI may still work because pnpm hoists from packages/vinext's devDeps, but anyone cloning a standalone example won't have it. Each example should add "@vitejs/plugin-react": "^5.1.4" to its dependencies.


Inline comments below on specific files.

Comment thread packages/vinext/package.json
Comment thread packages/vinext/src/index.ts
Comment thread packages/vinext/src/deploy.ts
@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk Bot commented Mar 13, 2026

Review submitted successfully. Here's a summary of the feedback I posted on PR #525:

Overall: Good change. Moving @vitejs/plugin-react from a hard dependency to a peer dependency with ^5.1.4 || ^6.0.0 is the right approach for letting users choose between v5 and v6.

Key feedback:

  1. Missing dependency in examples (most important): All examples under examples/ don't list @vitejs/plugin-react as a dependency. Since it was moved from vinext's dependencies to peerDependencies, it won't be installed transitively anymore. I verified with createRequire that the package is unresolvable from the example directories. Anyone cloning a standalone example will hit a runtime error. Each example needs to add @vitejs/plugin-react to its package.json.

  2. Peer dependency optionality: @vitejs/plugin-react isn't marked optional in peerDependenciesMeta, which means users who intentionally pass react: false will still get package manager warnings. Not blocking, but worth considering.

  3. Duplicate detection fragility: The duplicate plugin detection relies on plugin names starting with vite:react. If v6 changes plugin names (e.g., switching from Babel to SWC), the detection would silently stop working. Suggested adding a comment noting this assumption.

  4. Positive note on deploy.ts: The switch from _findInNodeModules to _isResolvable for both the new React plugin check and the MDX check is a good consistency improvement.

github run

@hyoban
Copy link
Copy Markdown
Contributor Author

hyoban commented Mar 13, 2026

All resolved

@james-elicx
Copy link
Copy Markdown
Collaborator

/bigbonk re-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.

Good change. Moving @vitejs/plugin-react from a hard dependency to a peer dependency is the right architectural move for supporting both v5 and v6 without forcing unnecessary installs.

The implementation is clean and thorough:

  • Dynamic import with createRequire resolution correctly handles monorepo hoisting
  • Duplicate plugin detection mirrors the existing RSC pattern
  • .catch() wrapper on the promise gives a clear vinext-prefixed error
  • All examples updated with the explicit dependency
  • check.ts conditionally shows App Router deps (not just always listing them)
  • deploy.ts consistently uses _isResolvable now (good cleanup of the old _findInNodeModules for MDX too)
  • Test coverage is solid — auto-injection, duplicate detection, init deps, deploy missing deps, check report formatting

Two minor non-blocking notes inline.

},
"peerDependencies": {
"@mdx-js/rollup": "^3.0.0",
"@vitejs/plugin-react": "^5.1.4 || ^6.0.0",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Non-blocking: @vitejs/plugin-react isn't listed in peerDependenciesMeta, so package managers will always warn when it's missing — even for users who intentionally pass react: false. This is a reasonable default since the vast majority of users need it, but worth being aware of if you get bug reports about spurious peer dep warnings from people using SWC or other JSX transforms.

// Assumes @vitejs/plugin-react top-level plugin names continue to use
// the vite:react* prefix across supported versions.
const reactRootPlugins = config.plugins.filter(
(p: any) => p && typeof p.name === "string" && p.name.startsWith("vite:react"),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The comment on line 1464-1465 about plugin name prefixes is good. Worth noting that @vitejs/plugin-react-swc uses vite:react-swc as its name — so if v6 adopts a different transform backend, the prefix would change. The current approach is consistent with the RSC detection pattern (which checks for name === "rsc"), so it's fine as-is. Just a heads-up for when v6 actually ships.

@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk Bot commented Mar 13, 2026

Review submitted with approval. Here's a summary of my review:

Approved — This is a well-executed change. The PR moves @vitejs/plugin-react from a hard dependency to a peer dependency (^5.1.4 || ^6.0.0), letting users choose between v5 and v6.

Key strengths:

  • Dynamic import with createRequire resolution correctly handles monorepo hoisting
  • Duplicate plugin detection mirrors the existing RSC pattern
  • Error messages include the package manager command (which already includes -D)
  • All 9 examples updated with the explicit dependency
  • check.ts conditionally shows App Router-only deps
  • deploy.ts cleanup: MDX check now uses _isResolvable consistently
  • Solid test coverage across all affected modules

Two non-blocking inline notes:

  1. @vitejs/plugin-react isn't marked optional in peerDependenciesMeta, so react: false users will get spurious warnings
  2. The duplicate detection relies on vite:react* plugin name prefix — if v6 changes the transform backend, the prefix may change

github run

@james-elicx james-elicx merged commit 21558f3 into cloudflare:main Mar 13, 2026
19 checks passed
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.

2 participants