vitejs / vitejs/vite-plugin-react

plugin-rsc: cross-origin stylesheet resources omit crossOrigin and can poison browser CORS cache

Open Beginner friendly
#1,464 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
1.2k
Forks
269
Avg merge
1d 3h
Merged PRs (30d)
19

Description

Summary

With plugin-rsc 0.5.34, both generated Resources stylesheet links and SSR ReactDOM.preinit(href, { as: 'style' }) omit crossOrigin. Cross-origin CSS can consequently be cached from a non-CORS request and fail a later CORS fetch of the same URL.

The omission also appears in main at df9f9959e3df0038b3f5af1247d9ec688f4754d2 (src/plugin.ts generateResourcesCode and src/ssr/shared.ts preloadDeps). I did not find a supported option controlling these attributes; cssLinkPrecedence does not address request mode.

Runnable minimal reproduction

https://gist.github.com/jaden-chen/64f2ea68397a9d5844c28da4abb71a74

Node 26, Vinext 1.0.0-beta.9, plugin-rsc 0.5.34, Vite 8.3.0, React 19.3.0. The fixture builds a tiny real App Router application and serves its generated assets from a second local origin. No service worker or application recovery code is present. It models an asset origin that returns ACAO and Vary: Origin only when an Origin header is sent (observed with R2), with immutable cache headers.

  1. Initial server-imported and client-component stylesheets load through links without crossorigin.
  2. Fetch those same URLs from JavaScript with default CORS mode.
  3. Chromium reuses the non-CORS response and rejects it because ACAO is missing.
  4. A cache-reload CORS fetch succeeds. This is not a missing allowlist or missing asset.
Expected / proposed correction

Consistent anonymous CORS for CSS resource generation, matching Vite's ordinary HTML stylesheet generation and RSC's adjacent module preload behavior:

  • crossOrigin: 'anonymous' in the generated Resources link props.
  • crossOrigin: 'anonymous' in SSR CSS preinit options.

A version-checked local patch to these paths passes initial rendering, navigation and warm-cache checks without a worker. The fixture also uncovered a separate Vinext next/dynamic preload omission, which is being reported there independently.

Happy to adjust the proposed correction if the intended contract is a configurable crossOrigin policy rather than a default. The reproduction intentionally distinguishes origin behavior from framework request consistency.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/plugin.ts at generateResourcesCode and in src/ssr/shared.ts at preloadDeps, then run the linked minimal reproduction against the cross-origin asset setup. Done means generated stylesheet links and SSR CSS preinit options consistently request anonymous CORS, while the reproduction's initial render, navigation, and warm-cache checks pass.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript, vite
Domain
tooling, web-dev
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.