Skip to content

feat(plugin-rsc): expose Node.js stream APIs - #1276

Open
switz wants to merge 2 commits into
vitejs:mainfrom
switz:feat/rsc-node-stream-apis
Open

feat(plugin-rsc): expose Node.js stream APIs#1276
switz wants to merge 2 commits into
vitejs:mainfrom
switz:feat/rsc-node-stream-apis

Conversation

@switz

@switz switz commented Jul 6, 2026

Copy link
Copy Markdown

Edit: Apologies, Claude went ahead and opened this PR automatically. This code was driven with Claude.

This closes my issue #1162 and addresses the feedback from the PR in #1164

Let me know if you want me to make any changes. Sorry for the quick trigger on the PR.

The flaw here is dual loading edge and node apis on the node path – if we want to refactor it, we can drop that. You'd know better than me if that's a big deal.


Closes #1162

The vendored react-server-dom-webpack package includes Node.js stream APIs (renderToPipeableStream, createFromNodeStream) that are faster than their Web Streams equivalents on Node.js, but they weren't exposed by @vitejs/plugin-rsc.

Approach

The server.node and client.node variants from react-server-dom-webpack are supersets of their .edge counterparts. So each new .node file re-exports everything from the existing edge-based module and adds only the Node.js-specific delta — no code duplication.

New entry points:

import { renderToPipeableStream } from '@vitejs/plugin-rsc/rsc.node'
import { createFromNodeStream } from '@vitejs/plugin-rsc/ssr.node'

Both also re-export all existing Web Streams APIs, so consumers can switch entry points without losing access to renderToReadableStream / createFromReadableStream.

Files

New (4 files):

  • src/react/rsc.node.ts — low-level wrapper, re-exports ./rsc + adds renderToPipeableStream
  • src/react/ssr.node.ts — low-level wrapper, re-exports ./ssr + adds createFromNodeStream
  • src/rsc.node.tsx — high-level entry, re-exports ./rsc + adds wrapped renderToPipeableStream with asset manifest enrichment
  • src/ssr.node.tsx — high-level entry, re-exports ./ssr + adds createFromNodeStream

Modified (2 files):

  • tsdown.config.ts — added 4 new entry points
  • src/types/index.ts — added PipeableStream, RenderToPipeableStreamOptions, CreateFromNodeStreamOptions

No changes to package.json (wildcard export covers new paths) or plugin.ts (vendor alias already handles .node variants).

Test plan

  • pnpm build compiles successfully with new entry points
  • tsc -b ./tsconfig.json passes
  • E2E test exercising the Node.js stream APIs (happy to add — would appreciate guidance on preferred approach, e.g. inline fixture variant of starter-extra that swaps the SSR entry to use createFromNodeStream)

@hi-ogawa hi-ogawa left a comment

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.

Thanks for PR. There has been some update on current /rsc structure https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-rsc/README.md#rsc-runtime-react-server-dom-api Can you align these node variant with new structure and API like:

  • /rsc.node
  • /rsc/server.node
  • /rsc/client.node
  • /rsc/static.node

Having an e2e would be also desired. A dedicated starter-like example under examples/node-stream could work. I have reworked test guidance a bit recently so please take a look https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-rsc/CONTRIBUTING.md#testing

switz and others added 2 commits August 16, 2026 10:40
… createFromNodeStream)

Re-export Node.js-native stream variants from react-server-dom-webpack
as new entry points (@vitejs/plugin-rsc/rsc.node, ssr.node) without
duplicating existing code — each .node file re-exports from its edge
counterpart and adds only the Node-specific APIs.

Closes vitejs#1162

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restructure Node.js stream entry points from flat paths (/rsc.node,
/ssr.node) to match the existing sub-path pattern:
- /rsc/server.node (renderToPipeableStream)
- /rsc/client.node (createFromNodeStream)
- /rsc/static.node (prerenderToNodeStream)
- /rsc.node (barrel re-export of server.node + client.node)

Add .node vendor subpaths to optimizeDeps.include so CJS vendor files
are properly pre-bundled in dev mode.

Add examples/node-stream demonstrating Node.js stream APIs with an
e2e test covering both dev and build modes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@switz
switz force-pushed the feat/rsc-node-stream-apis branch from 7747f53 to b1baf48 Compare August 16, 2026 15:15
@switz
switz requested a review from hi-ogawa August 16, 2026 15:16
@switz

switz commented Aug 16, 2026

Copy link
Copy Markdown
Author

Rebased the branch and updated everything based on your feedback. Node stream apis are now aligned with the sub-path pattern.

Also added an e2e test. Thanks

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.

@vitejs/plugin-rsc — expose Node.js stream APIs (renderToPipeableStream, createFromNodeStream)

2 participants