Skip to content

feat(rsc): add setServerCssLinkProps to set a nonce on server css links - #1529

Draft
hi-ogawa wants to merge 1 commit into
mainfrom
feat/rsc-css-link-props
Draft

hi-ogawa wants to merge 1 commit into
mainfrom
feat/rsc-css-link-props

Conversation

@hi-ogawa

Copy link
Copy Markdown
Contributor

The <link rel="stylesheet"> elements that rsc renders for server components' CSS, both the auto-injected ones and the ones from import.meta.viteRsc.loadCss(), have no nonce. A nonce-only CSP style-src blocks them, and a framework has no way to add one.

This adds an experimental setServerCssLinkProps to @vitejs/plugin-rsc/rsc/server. A framework registers it once, and the plugin calls it while React renders each link, so it can read the nonce from the framework's own request-scoped storage. For now it supports only nonce.

const nonceStorage = new AsyncLocalStorage<string | undefined>()
setServerCssLinkProps(() => ({ nonce: nonceStorage.getStore() }))

const stream = nonceStorage.run(nonce, () => renderToReadableStream(payload))

#1528 solves the same problem with a nonce render option, which the plugin carries to the links through its own AsyncLocalStorage. Frameworks already keep request state in their own AsyncLocalStorage, and React renders the links inside the caller's async context either way. So a hook lets the plugin stay out of request scoping entirely, without depending on the global AsyncLocalStorage that rsc:inject-async-local-storage sets up for React. The framework then decides which renders get a nonce, for example leaving it out of a render whose output is cached across requests, the same way it already keeps cookies and headers out of cached renders.

This still doesn't make a nonce-only style-src work on its own:

  • On client navigation, React inserts the links into the current document, so they need that document's nonce, which the framework has to carry into navigation requests itself. examples/basic doesn't, and gives those links no nonce.
  • Client components' CSS is linked during SSR through ReactDOM.preinit, which drops nonce for stylesheets.

…inks

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

1 participant