-
-
Notifications
You must be signed in to change notification settings - Fork 225
feat(rsc): add resolved-id proxy for virtual modules + document ?direct limitation #1050
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+347
−2
Conversation
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
- Add tests for virtual module with 'use client' directive - Add tests for virtual CSS modules in server components - Add tests for virtual CSS modules imported in client components
- Add virtual module with 'use client' directive - Add virtual CSS modules (server and client) - Add @nojs test to verify no FOUC
…t references Virtual modules use \0 prefix internally in Vite, but this cannot be used as an import specifier when generating client reference code. Strip the prefix to allow virtual modules with 'use client' directive to work correctly.
Introduce vitePluginResolvedIdProxy() to handle virtual modules with \0 prefix
in import specifiers and CSS hrefs. This provides a cleaner alternative to
stripping the \0 prefix directly.
Input/Output:
- toResolvedIdProxy("\0virtual:test.css")
=> "virtual:vite-rsc/resolved-id/__x00__virtual:test.css"
- fromResolvedIdProxy("virtual:vite-rsc/resolved-id/__x00__virtual:test.css")
=> "\0virtual:test.css"
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Virtual CSS modules return JS wrapper instead of raw CSS in dev mode. Co-Authored-By: Claude Opus 4.5 <[email protected]>
Co-Authored-By: Claude Opus 4.5 <[email protected]>
Expand the TODO comment into comprehensive documentation explaining: - Standard virtual module pattern with \0 prefix - How Vite's ?direct CSS mechanism works - Why virtual modules break (exact string matching vs query injection) - Why regular CSS files work (query-stripping fallback) - Conclusion: this is a Vite limitation, not RSC plugin issue Co-Authored-By: Claude Opus 4.5 <[email protected]>
Remove resolved-id-proxy workaround for CSS hrefs and instead show both working and failing patterns in e2e tests: - Query-aware virtual CSS: strips ?direct in resolveId, preserves in resolved id, strips in load. Works with <link> in dev mode. - Exact-match virtual CSS: standard pattern with exact string matching. Works via JS import but fails via <link> in dev (Vite limitation). This demonstrates the Vite limitation documented in resolved-id-proxy.ts and provides a reference implementation for users who need virtual CSS to work with SSR <link> tags. Co-Authored-By: Claude Opus 4.5 <[email protected]>
… query/exact) Demonstrate Vite's ?direct limitation with comprehensive test cases: Server CSS (loaded via <link>): - Query-aware: works in both dev and build - Exact-match: fails in dev (Vite limitation), works in build Client CSS (loaded via JS import): - Query-aware: works in both dev and build - Exact-match: works in both dev and build (no ?direct in JS imports) In noJS mode, all CSS is loaded via <link>, so both server and client exact-match fail in dev mode. Co-Authored-By: Claude Opus 4.5 <[email protected]>
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.
Summary
vitePluginResolvedIdProxy()to enable virtualuse clientmodulesuse client, CSS)?directquery limitation for virtual CSS modulesThe problem
Virtual modules in Vite use
\0prefix for resolved IDs (e.g.,\0virtual:test-virtual-client). However, when RSC generates client reference imports, these\0-prefixed IDs cannot be used directly in import specifiers.The fix
The resolved-id proxy encodes
\0so it can be used in import specifiers:The
vitePluginResolvedIdProxy()then resolves these back to the original\0-prefixed IDs. This enables virtualuse clientmodules to work correctly in RSC.Side note: Virtual CSS and
?directlimitationDuring this work, we investigated why virtual CSS modules don't work with SSR
<link>tags in dev mode.How Vite's
?directworksWhen a browser requests
<link href="xxx.css">, Vite middleware injects?directquery. The CSS plugin checks this to return raw CSS instead of a JS wrapper.Why virtual CSS breaks
Standard virtual module plugins use exact string matching:
For real files, Vite retries with query stripped. Virtual modules don't benefit from this fallback.
Workaround for users
Make virtual CSS plugins query-aware:
E2E test matrix
<link>)This is a Vite limitation. Proper fix would require Vite to provide query-aware virtual module helpers or apply query-stripping fallback to virtual modules.
🤖 Generated with Claude Code