Skip to content

feat(plugin-rsc): allow to control whether CSS links use React's precedence attribute#1064

Merged
hi-ogawa merged 3 commits intovitejs:mainfrom
schiller-manuel:cssLinkPrecedence
Jan 19, 2026
Merged

feat(plugin-rsc): allow to control whether CSS links use React's precedence attribute#1064
hi-ogawa merged 3 commits intovitejs:mainfrom
schiller-manuel:cssLinkPrecedence

Conversation

@schiller-manuel
Copy link
Contributor

@schiller-manuel schiller-manuel commented Jan 16, 2026

Summary

Adds a new cssLinkPrecedence option to control whether CSS links use React's precedence attribute.

  • When true (default): CSS links include precedence="vite-rsc/importer-resources" or precedence="vite-rsc/client-reference"
  • When false: CSS links are rendered without the precedence attribute

Usage

rsc({
  cssLinkPrecedence: false, // disable React's precedence attribute on CSS links
})

Changes

  • Added cssLinkPrecedence option to RscPluginOptions (marked as @experimental)
  • Updated generateResourcesCode to conditionally include precedence
  • Updated preloadDeps in ssr.tsx to respect the setting

@schiller-manuel schiller-manuel changed the title allow to control whether CSS links use React's precedence attribute feat(plugin-rsc): allow to control whether CSS links use React's precedence attribute Jan 16, 2026
Copy link
Contributor

@hi-ogawa hi-ogawa left a comment

Choose a reason for hiding this comment

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

I'm seeing this error on console when cssLinkPrecedence: false.

react-dom_client.js?v=3a470fe3:16505
Cannot render a <link rel="stylesheet" /> outside the main document without knowing its precedence. Consider adding precedence="default" or moving it into the root <head> tag.

I'm fine to have this as option, but I'll note this API as @experimental as I'm not sure what the ideal shape of this yet in the long run.

@hi-ogawa
Copy link
Contributor

Research on React's precedence attribute for stylesheets

Note: This comment was AI-generated based on research.

How precedence Works

When you add precedence to a <link rel="stylesheet">:

  1. React automatically moves it to <head> - regardless of where you render it in the React tree
  2. Suspense integration - the component suspends until the stylesheet loads
  3. Deduplication - multiple links to the same stylesheet result in only one <link> in the DOM
  4. Ordering - React groups stylesheets by precedence value and maintains insertion order within groups

The Problem Without precedence

When precedence is omitted:

  • No special behavior - React treats it as a regular element
  • No automatic head placement - the link renders wherever it is in the tree
  • The warning appears - React complains because a <link rel="stylesheet"> rendered outside <head> without precedence is problematic

The error message is essentially saying: "If you want to render this outside the head, you need to tell me the precedence so I can move it to the head for you."

Why Someone Might Want cssLinkPrecedence: false

Possible reasons could be:

  1. Custom CSS loading strategy - wanting to control the loading order manually
  2. Avoiding Suspense behavior - precedence-enabled links cause Suspense boundaries to wait for CSS to load
  3. SSR/streaming concerns - some edge cases with streaming SSR might have issues with React's stylesheet management

What This Means

The current implementation with cssLinkPrecedence: false will show console warnings in development. To avoid the warning, the CSS links would need to be:

  • Rendered inside <head> directly, OR
  • Given some precedence value (even "default")

@schiller-manuel - Could you share what specific problem you're trying to solve by disabling precedence? That would help determine the right approach.

References:

@hi-ogawa
Copy link
Contributor

Considering #1065, is it more preferable to not including <link> / preinit(style) from @vitejs/plugin-rsc at all?

@hi-ogawa
Copy link
Contributor

I'm still unsure the full viability of style without precedence (for server component case, client component case, CSR case, SSR case), but we can iterate as needed, so merging.

@hi-ogawa hi-ogawa merged commit d143cd5 into vitejs:main Jan 19, 2026
18 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