fix(hmr): resolve virtual module URLs correctly for HMR updates and invalidation#22098
Open
bolasblack wants to merge 1 commit intovitejs:mainfrom
Open
fix(hmr): resolve virtual module URLs correctly for HMR updates and invalidation#22098bolasblack wants to merge 1 commit intovitejs:mainfrom
bolasblack wants to merge 1 commit intovitejs:mainfrom
Conversation
…nvalidation Virtual modules (with `\0` prefix) have a URL mismatch between client and server: the browser uses `/@id/__x00__virtual:...` but the server's module graph stores `mod.url` as the bare specifier `virtual:...` (without the `\0` prefix). This causes two issues: 1. `js-update` messages for virtual module HMR boundaries use the wrong path, so the browser silently ignores the update. 2. `import.meta.hot.invalidate()` sends the client-side URL back to the server, which fails to look up the module in `urlToModuleMap`. Fix: In `updateModules`, use `mod.id` (which preserves the `\0` prefix) instead of `mod.url` for virtual modules, so `wrapId` correctly generates the `/@id/__x00__...` URL. In `invalidateModule`, fall back to `idToModuleMap.get(unwrapId(path))` to resolve the client-side URL.
bolasblack
added a commit
to bolasblack/shadow-cljs-vite-plugin
that referenced
this pull request
Apr 1, 2026
- AGD-007: add 'Known Issue' section with verified root cause (URL mismatch between client /@id/__x00__ and server mod.url), link to vitejs/vite#22098, and simplified code path after fix is merged - README: add 'Upstream Contributions' section (shadow-cljs#1249, vite#22098)
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
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.
import.meta.hot.invalidate()and HMRjs-updatesilently fail for virtual modules.Root cause
Virtual modules have a URL mismatch between client and server:
/@id/__x00__virtual:my-modulemod.url(server)virtual:my-moduleThis is because
mod.urldoesn't contain the\0prefix — it stores the bare specifier. WhennormalizeHmrUrl(mod.url)runswrapId(), it produces/@id/virtual:my-module(missing__x00__), which doesn't match the browser-side URL.This breaks two things:
js-updatefor virtual module HMR boundaries —accept()callback never firesinvalidate()— server can't find the module inurlToModuleMapFix
hmr.ts: Usemod.id(which has\0) instead ofmod.urlfor virtual modules, sowrapIdgenerates the correct/@id/__x00__...path.environment.ts: Fall back toidToModuleMap.get(unwrapId(path))ininvalidateModule.Test
Added
'invalidate virtual module propagates to importers'inplayground/hmr— a virtual module thataccept()s theninvalidate()s. Fails without fix, passes with it.