mirror of
https://github.com/cloudflare/vinext.git
synced 2026-05-09 08:25:34 +02:00
[GH-ISSUE #1001] Internal 'use client' shims use relative imports, breaking @vitejs/plugin-rsc's client-in-server-package-proxy against the exports field #219
Labels
No labels
enhancement
enhancement
good first issue
help wanted
nextjs-tracking
nextjs-tracking
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/vinext#219
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @eashish93 on GitHub (May 1, 2026).
Original GitHub issue: https://github.com/cloudflare/vinext/issues/1001
Summary
vinext's internal server modules import their own
'use client'shims via relative paths like:@vitejs/plugin-rsc'spackageSourcetracking only fires for bare specifier imports (vinext/shims/X), not relative ones. When plugin-rsc later sees the resolved file is'use client'and insidenode_modules/, it falls back to theclient-in-server-package-proxybranch and generates a virtual module that imports via the absolute filesystem path:Vite's resolver respects the package's
exportsfield. vinext'sexportsonly exposes./shims/*→./dist/shims/*.js. The absolute path…/vinext/dist/shims/X.jsdoesn't match any exports key, so resolution fails and the dev server returns:The file IS on disk. The fail is the
exportsfield gate, not fs absence.Reproduce
Minimal vinext app (just
app/page.tsx+app/layout.tsx) on:vinext@0.0.45@vitejs/plugin-rsc@0.5.25vite@8.0.10vinext devboots successfully. Loading any page that triggers the app router (i.e. anything reachingdist/server/app-page-route-wiring.jsordist/server/app-page-boundary-render.js) surfaces the error overlay above. Affects every'use client'shim (layout-segment-context,link,navigation,error-boundary,form,script,slot).Root cause (in plugin-rsc terms)
In
@vitejs/plugin-rsc/dist/plugin-BhzHKRFo.js:vinext's relative
../shims/X.jsimports never setpackageSources, so the broken branch always wins for these files.Proposed fix
vinext should import its own
'use client'shim files via the bare specifiervinext/shims/<name>instead of relative paths indist/server/*. The exports field already maps these:So changing:
to:
makes plugin-rsc's
resolveIdhook (which runs for bare specifiers) populatepackageSources, taking theclient-package-proxybranch instead and generating a virtual module that imports the bare specifier — which Vite's resolver handles correctly via the exports map.Files that need this rewrite (grep for
from "\.\./shims/.*\.js"indist/server/):dist/server/app-page-route-wiring.js—LayoutSegmentProviderdist/server/app-page-boundary-render.js—LayoutSegmentProviderdist/index.js— references the same shims viapath.join(shimsDir, …)error-boundary.js,link.js,navigation.js,script.js,slot.js,form.js,client-hook-error.js(Source-level: probably the
importstatements insrc/server/*.tsneed to change from../shims/Xto the package's own bare specifier.)Workaround
Patch
vinext/package.jsonpost-install to also expose./dist/shims/*.jsin the exports map:This makes the absolute path resolvable, but it leaks internal paths. Real fix is in vinext's import statements.
Environment
@Divkix commented on GitHub (May 1, 2026):
Alright, I dug into this. The issue is real — here's what I found.
The relative imports are everywhere. 56+ instances of
from "../shims/..."acrosssrc/server/,src/build/, andsrc/client/. The builtdist/output has the same relative imports —dist/server/app-page-route-wiring.jsimportsLayoutSegmentProvider,ErrorBoundary,MetadataHead,Slot, andChildrenall via../shims/. Exactly what you described.The @vitejs/plugin-rsc code path checks out. In
plugin-DMfc_Eqq.js(that's 0.5.23, but the logic is the same),packageSources.set()at line 1356 only fires whenbareImportRE.test(source)passes. Relative imports never match. So when the fallback at line 1217 runs, it generates a proxy module with the absolute filesystem path. That proxy contains:And that's where it breaks. Node.js 24 confirms:
Weirdly, it doesn't break locally. I ran
vp devon theapp-basicfixture and it serves fine — 200 OK, full HTML.vp buildpasses too. We're onvite@8.0.8via voidzero's build — I'm guessing their fork handles absolute-path resolution differently than standard Vite 8.0.10. For anyone installing vinext from npm with standard Vite, the exports field enforcement kicks in and you get theFailed to resolve importerror overlay.The fix is straightforward. Change
from "../shims/X.js"tofrom "vinext/shims/X"everywhere. Theexportsfield already maps./shims/*→./dist/shims/*.js. One file (deploy.ts:433) already does this correctly:About 56 lines to update across ~30 files. The
packageSourcesmap would then be populated for these imports, and the RSC plugin would take the workingclient-package-proxybranch instead of the broken one.Files that need changing (just the highlights, not exhaustive):
src/server/app-page-route-wiring.tsx—ErrorBoundary,LayoutSegmentProvider,MetadataHead,Slotsrc/server/app-page-boundary-render.ts—ErrorBoundary,LayoutSegmentProvider,MetadataHead,client-hook-errorsrc/server/dev-server.ts— 4 shim importssrc/server/prod-server.ts—request-contextsrc/server/app-ssr-entry.ts—navigation,script-nonce-context,slotsrc/server/app-browser-entry.ts—navigation,slot,url-safetysrc/server/app-route-handler-dispatch.ts—fetch-cache,headers,navigation,request-context,unified-request-contextsrc/server/app-middleware.ts—headers,navigationsrc/server/app-route-handler-execution.ts—headers,request-context,cache,serversrc/build/prerender.tssrc/cloudflare/kv-cache-handler.tssrc/client/vinext-next-data.tssrc/config/next-config.tssrc/server/isr-cache.ts,src/server/instrumentation.ts,src/server/file-based-metadata.ts, and about 15 more server filesThe dev server works locally because of the voidzero Vite build, but anyone on standard Vite 8 is hitting this. Worth fixing before more users run into it.
@james-elicx commented on GitHub (May 2, 2026):
I can't see a reference to this problem in that blog post. Please can you share what you're referring to?
@eashish93 commented on GitHub (May 2, 2026):
I've been testing vinext on a new project (running on Cloudflare Sandbox containers) and encountered many bugs simultaneously which I already filled, so maybe that's why the hallucination by opus 4.7 on citation.
This part: https://waku.gg/blog/migration-to-vite-plugin-rsc#transforming-server-packages is actually related to issue #1008 somehow.
I'll edit the issue and remove the related upstream part.
@james-elicx commented on GitHub (May 2, 2026):
I see, no worries. I want to try and reproduce this issue this afternoon before merging the pr - concerned this wasn't caught by existing e2es. If you can share a minimal repro that would be super handy as well.
@eashish93 commented on GitHub (May 2, 2026):
Hard to reproduce it normally, but it happen inside sandbox container. I tried it with codesandbox, but I guess that may not be sufficient: https://codesandbox.io/p/devbox/rsc-vinext-repro-kcddvm
If I able to create minimal repro from my codebase locally, I'll paste it here soon.
@james-elicx commented on GitHub (May 2, 2026):
I've tried reproducing locally in individual projects, inside Docker containers, inside the monorepo, etc. but had no luck unfortunately...
Did (somewhat quickly) try a couple patches in the rsc plugin the codesandbox but continued having issues, so I'll merge that PR.
@james-elicx commented on GitHub (May 2, 2026):
I would note that without a reproduction outside of codesandbox that can be encountered via direct navigation rather than a curl for internal vite logic, there's no guarantee this won't regress.