fix: invalidate Vite module graph on template/style HMR updates#158
Merged
Brooooooklyn merged 1 commit intovoidzero-dev:mainfrom Mar 23, 2026
Merged
Conversation
Two fixes for HMR reliability: 1. After sending the angular:component-update WS event, call server.moduleGraph.invalidateModule() so that Vite's transform cache is cleared and full page reloads serve fresh content. 2. In handleHotUpdate, skip the full-reload for component .ts files that have a pending HMR update (pendingHmrUpdates). Template/style changes trigger handleHotUpdate for the owning .ts file via Vite's module graph dependency tracking, but the .ts file wasn't actually edited. Without this check, the full-reload overrides the HMR update.
a985d43 to
2a03a3d
Compare
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.
Problem
When a template or style file changes during development, the Vite plugin's custom
fs.watchcallback correctly:resourceCacheangular:component-updateWebSocket event to the browserHowever, it never calls
server.moduleGraph.invalidateModule()for the owning component module. This means Vite's transform cache retains the stale compiled output from the previous template/style content.Symptoms
Stale content after full page reload: HMR live updates work correctly (the middleware reads the template fresh and compiles a new HMR module), but a full page reload serves the old compiled component because Vite returns its cached transform result.
Unreliable HMR when global styles are present: When global stylesheets are in the module graph (e.g., injected via
<link>tags), Vite occasionally re-evaluates module dependencies using the stale transform cache, causing some HMR updates to appear to be skipped. Users see the update applied only after saving multiple times.Reproduction
liveReload: true.htmlfileRoot cause
In
configureServer, thefs.watchcallback (line 344) sends the HMR WebSocket event but does not invalidate the component module in Vite's module graph:Fix
Add
server.moduleGraph.invalidateModule()after the WebSocket event is sent. This ensures Vite re-transforms the component module on the next full request while the live HMR update is unaffected:The invalidation is placed after
ws.sendso the in-flight HMR update completes via the custom middleware path. TheinvalidateModulecall only clears Vite's cached transform result — it does not trigger a reload or interfere with the custom HMR mechanism.Test plan
<link>tag) → verify template HMR remains reliable.tsfile → verify full reload still triggers (unchanged behavior)