Repository navigation
fix(rsc): reuse server css resources element across renders - #1534
Open
james-elicx wants to merge 3 commits into
Open
james-elicx wants to merge 3 commits into
james-elicx wants to merge 3 commits into
Conversation
james-elicx
marked this pull request as ready for review
October 28, 2026 17:54
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
rscCssTransformwraps every exported server component in a CSS-importing module so that each render emitsimport.meta.viteRsc.loadCss(). The generatedResourcescomponent builds new<link>elements on every call, so React Flight serializes the full set of links again for every instance. React dedupes the stylesheets in the DOM, but the RSC payload (and the inlined payload in the SSR HTML) grows linearly with the number of instances.We hit this in a real app: about 91 kB of a page's payload was the same 7 stylesheet links, repeated 398 times, once per instance of a server component that imports CSS.
depsis static for eachvirtual:vite-rsc/css?module, so this PR creates the element once and returns the same object fromResources. Flight already serializes an element it has written before as a short back-reference (e.g."$0:props:children:0:props:children:0"), so every instance after the first costs a few bytes instead of the full link list.Every instance still carries its links (as a reference), so stylesheet hoisting, precedence ordering and Suspense behaviour are unchanged. Flight tracks written objects per request, so sharing the element across requests is safe. In dev the virtual module is regenerated when its CSS changes, so the cached element can't go stale.
For scale, a standalone Flight render of 398 instances with 7 links each:
The new e2e test renders a CSS-importing server component N times (
?test-style-server-repeated=N) and checks that the number ofdata-rsc-css-hrefentries in the RSC payload is the same for N=1 and N=5, and that every instance is styled after hydration. It fails onmainin both dev and build (20 vs 24 and 9 vs 13) and passes with this change.