Skip to content

fix(e2e): preserve RSC server asset URLs - #2291

Merged
dai-shi merged 1 commit into
wakujs:mainfrom
dai-shi:fix/rsc-asset-file-url
Sep 4, 2026
Merged

fix(e2e): preserve RSC server asset URLs#2291
dai-shi merged 1 commit into
wakujs:mainfrom
dai-shi:fix/rsc-asset-file-url

Conversation

@dai-shi

@dai-shi dai-shi commented Sep 4, 2026

Copy link
Copy Markdown
Member

Resolve server assets relative to the emitted chunk with newer Vite versions.

Keep browser asset URLs handled by Vite.

Resolve server assets relative to the emitted chunk with newer Vite versions.
Keep browser asset URLs handled by Vite.

Background

e2e/fixtures/rsc-asset covers asset references originating inside an RSC, in
two directions that have to resolve differently within the same rsc
environment:

  • new URL('./test-server.txt', import.meta.url) + readFileSync needs a URL
    the Node process can open on disk, relative to the emitted chunk.
  • ./test-client.txt?no-inline rendered as an <a href> needs a public URL the
    browser can fetch (/assets/...).

Vite doesn't handle new URL(..., import.meta.url) for SSR, so the fixture ships
its own plugin that rewrites the call into this.emitFile() +
new URL(import.meta.ROLLUP_FILE_URL_<id>). That relied on Rollup's default
resolveFileUrl, which produces new URL('./x', import.meta.url).href.

vitejs/vite#22888 ("use import.meta.ROLLDOWN_FILE_URL_* for assets in JS")
added a resolveFileUrl hook to vite:asset. It was written for Vite's own
emitters, but resolveFileUrl is a global Rollup hook, so it also intercepts
references emitted by user plugins. Those have no asFileUrl metadata attached,
so they fall through to toOutputFilePathInJS, which for a server-consumer
environment always returns a base-joined path.

The fixture's server chunk therefore built as:

const testServerTxtUrl = new URL("/assets/test-server-BTC3QXxI.txt");

new URL() on a root-relative path with no base throws, so the RSC render failed
with TypeError: Invalid URL, data-testid="server-file" never rendered, and
[chromium-prd] rsc-asset › basic timed out. The client ?no-inline half was
unaffected. Failing job:

This change

The plugin implements its own resolveFileUrl, scoped to the reference IDs it
emitted, and returns null for everything else so Vite continues to handle
browser asset URLs. enforce: 'pre' is required because resolveFileUrl is a
first hook and vite:asset is registered ahead of normal user plugins, so
without it the hook is never consulted.

Whether Vite intends to intercept third-party file references is a question for
upstream; this fixture works either way, since its hook returns first.

Resolve server assets relative to the emitted chunk with newer Vite versions.

Keep browser asset URLs handled by Vite.
@vercel

vercel Bot commented Sep 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
waku Ignored Ignored Preview Sep 4, 2026 5:15am UTC

Request Review

@pkg-pr-new

pkg-pr-new Bot commented Sep 4, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/waku@2291

commit: 61ca033

@dai-shi
dai-shi merged commit 3068808 into wakujs:main Sep 4, 2026
135 of 157 checks passed
@dai-shi
dai-shi deleted the fix/rsc-asset-file-url branch September 4, 2026 13:31
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