Vite HMR and Browser WebSocket Integration: Managing Module Graph Invalidation
0 reputation · 12 Dec 2023, 19:19 UTC
0 reputation · 12 Dec 2023, 19:19 UTC
Vite utilizes a WebSocket connection to facilitate Hot Module Replacement (HMR), allowing the server to push module invalidation events to the browser client based on the internal module graph. When a file is modified, Vite determines the minimum set of affected modules to update via the import.meta.hot interface.
A critical boundary exists when the module graph contains circular dependencies or when the HMR API cannot resolve a clean update path. In these scenarios, Vite is designed to fall back to a full page reload to ensure state consistency, which disrupts the development experience by resetting the application state.
Given the reliance on the WebSocket handshake and the module graph's dependency tracking, there is uncertainty regarding the precise trigger threshold for a full reload versus a partial HMR update in complex dependency trees.
31275 reputation · 13 Dec 2023, 02:00 UTC
Vite abandons Hot Module Replacement and issues a full page reload when the module graph cannot guarantee a safe incremental update. The decision is made on the server after computing the minimal affected set; the client then either applies the HMR payload or reloads the page.
import.meta.hot.accept handler, or the handler throws/returns false.If the WebSocket link between the dev server and the browser is closed, experiences rapid reconnects, or its message queue is overwhelmed by rapid‑fire file saves, Vite treats the connection as unreliable. In that case it initiates a full reload to resynchronize client and server state, even when the module graph would otherwise support a partial HMR update.
vite dev and open the browser console; filter for [HMR] logs.[HMR] Update applied (partial) or [HMR] Full reload.import.meta.hot.accept in a modified module and save; the console should show a full reload.If you can confirm whether you observe WebSocket close or error events in the DevTools Network tab, that would help determine if the WS state is the primary cause of the reload.
Use comments to ask for clarification. Post a solution as an answer.
31,275 reputation · 13 Dec 2023, 01:40 UTC
When a file changes, Vite’s dev server first computes the minimal set of modules that need updating. It then walks the import.meta.hot.accept acceptance chain for each of those modules. If any module in the chain lacks an accept handler, or its handler returns false (or throws), the server sends a WebSocket message with { type: 'full-reload' }. The client treats any non‑update message as a full reload, discarding pending HMR updates and executing window.location.reload(). For a successful HMR step the payload is { type: 'update', payload: [changedModuleIds] }, containing the exact modules to replace. This message structure is why a circular dependency that blocks a deterministic acceptance chain inevitably results in a full‑reload message, even though the underlying WebSocket connection remains healthy.