-
Notifications
You must be signed in to change notification settings - Fork 48.4k
feat: add react-server-dom-vite #33152
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
base: main
Are you sure you want to change the base?
Conversation
wip: copy parcel to vite wip: add __vite_rsc_preload__ and __vite_rsc_require__ wip: more rename wip: dev only wip: rename wip: remove parcelRequire wip: build prod wip: move findSourceMapURL to client option chore: comment chore: use __vite_rsc_preload__ only wip: fix findSourceMapURL wip: add fixtures/flight-vite wip: build fix: ssr client reference modulepreload wip: add setPreloadModule API refactor: abstract runtime wip: rename createClientReference to registerClientReference like webpack wip: tweak createServerReference refactor: remove unused wip: remove setServerCallback and align with webpack chore: comment chore: rename parcel to vite chore: prettier chore: lint chore: fix flow fix: global async reference cache wip: add ClientManifest type chore: lint chore: add css example wip: remove caching chore: add suspense example chore: rename mini to basic chore: fix streaming in vite preview feat: support prepare destination chore: cleanup test: tweak feat: add findSourceMapURL test: tweak fixture chore: cleanup test: normalize reference key chore: fix actions imported from client + preserve `createServerReference` position chore: temporary references chore: use `@hiogawa/transforms` in fixture chore: test temporary reference + early hydration chore: move code chore: test nonce in fixtures chore: fix deps chore: comment fix: allow unsafe-eval during dev for `createFakeFunction` chore: add inline action chore: copy transform utils to fixture chore: comment and readme
I initially didn't have css import handling, but now I just pushed one approach I've been thinking. This requires "prepare destination" to also handle |
Summary
As a continuation from the discussion on Jacob's PR #31768, this is a new PR to add the
react-server-dom-vite
package andfixtures/flight-vite
. To begin with, thank you to the React team for the patience with multiple PR iterations and for providing reviews. I also want to thank the Vite ecosystem for demonstrating Vite RSC integrations. I've learned fundamental concepts from existing Vite RSC frameworks and they are essential to reach this PR.Firstly, let me clarify a bundler-level characteristic that affects how RSC integration is approached for Vite. (This has been raised in past PRs as well, but I want to provide fuller context.)
modulepreload
. On the server, there's no alternative other than importing the chunk itself. (These are bundler-level and ESM runtime-level design concerns, and we assume Vite users are aware of them as a trade-off. It might still be interesting to find ways to circumvent and optimize this in userland, potentially suggest them as general bundler-level features, or employ new ESM specifications, but that's not the current focus for Vite RSC adoption.)modulepreload
injection of dependency chunks at runtime in the browser. Therefore, encodingchunks
into the RSC payload seems unnecessary, also with the fact that there's no way to preload ESM chunks on the server. (However, relying on Vite's preload feature might be considered an "anti-RSC" concept, since it essentially bakes the entire client manifest into the main browser bundle instead of sending chunk metadata as needed from the server. My current take (and thus this PR) is that since most Vite apps (both SPA and SSR) assume this feature, we can just use it, but challenging Vite's default mechanism might be intersting. Further discussion is very welcome.)fixtures/flight-vite
assumes that both SSR and RSC run on the same Node.js runtime as the main CLI process during development. However, this doesn't have to be the case in actual frameworks (for example, Jacob and RedwoodJS uses Cloudflare: https://github.com/redwoodjs/sdk). Therefore, a certain degree of generalization is required to makereact-server-dom-vite
portable for such usages (though this is mostly a concern for the plugin API, not the runtime API, and I haven't yet put any plugins at thereact-server-dom-vite
level).Given this background, notable differences of
react-server-dom-vite
compared to otherreact-server-dom
integrations are:setPreloadModule(loadModule: (id: string) => Promise<unknown>)
API.Add(EDIT: removed sincemoduleLoading.prepareDestinationManifest
to pass browser chunk mapping to SSR directly for "prepare destination".setPreloadModule(...)
alone can handle the same logic on user land)setPreloadModule
. Also, chunks do not need to be encoded in the RSC payload.?t=
for proper client reference HMR, but clearing the cache requires more logic, so I haven't attempted this at the moment.)Although this is the API I've currently implemented for the
fixtures/flight-vite
demo, I'm happy to iterate on the exact shape through discussions with the React team and Vite framework maintainers.In terms of "RSC spec" compliance,
fixtures/flight-vite
might look like it's achieving proper semantics. However, for transparency, I'm mentioning again here that supporting"use client"
insidenode_modules
can be difficult in some cases during dev. Here is an example repository to demonstrate such behaviors: https://github.com/hi-ogawa/rsc-tests. Supporting it case by case based on framework-side heuristics or additional user-side configuration is likely possible (for example, moving a client boundary fromnode_modules
to "user code" by re-exporting locally is an obvious workaround), but handling all cases uniformly behind the scenes as per the "RSC spec" is a challenge with the current unbundled dev. Eventually, this issue should disappear when we build RSC on top of a fully bundled development server with Vite/Rolldown. So, at the moment, I'd like each framework (and myself) to continue exploring approaches to support each case as best as possible.In parallel with addressing any feedback here, I'm going to test
react-server-dom-vite
in existing Vite RSC frameworks. For example, I have PRs on Waku (wakujs/waku#1393), RedwoodJS (redwoodjs/sdk#360), and my own plugin (hi-ogawa/vite-plugins#768) to preliminarily test with a local build of the package. My local build is pushed to my repository, so it can be installed via"react-server-dom-vite": "https://github.com/hi-ogawa/vite-plugins/raw/refs/heads/04-24-refactor_rsc_use_react-server-dom-vite/react-server-dom-vite-19.1.0.tgz"
inpackage.json
. Anyone interested is welcome to test the package. It's normally hard to implement "prepare destination" usingreact-server-dom-webpack
, so it might be interesting to see how switching toreact-server-dom-vite
helps.My further plan for
react-server-dom-vite
is to publish a polished version offixtures/flight-vite/basic
to provide an out-of-the-box, "framework-less" RSC experience on Vite (something similar to Parcel). This is intended to be "framework-less", but it's likely not directly reusable for more opinionated frameworks (for example, a framework might assume a custom environment like RedwoodJS and Cloudflare, or employ its own file system conventions and transforms such as "use cache"). However, certain core aspects of the currentfixtures/flight-vite/basic
should be reusable (such asvite-utils.ts
,findSourceMapURL
, and a bunch of virtual modules). I'll try to find a way to extract the common parts and provide a helper package for Vite RSC frameworks (or eventually move them intoreact-server-dom-vite
).How did you test this change?
Integration tests are included in
fixtures/flight-vite
. Please take a lookfixtures/flight-vite/README.md
for the detail.