vitejs / vitejs/vite-plugin-react
plugin-rsc: cross-origin stylesheet resources omit crossOrigin and can poison browser CORS cache
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.
- Initial server-imported and client-component stylesheets load through links without crossorigin.
- Fetch those same URLs from JavaScript with default CORS mode.
- Chromium reuses the non-CORS response and rejects it because ACAO is missing.
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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