How does Vite's HMR system work?
How does Vite's HMR system work?
About vitejs/vite · 2 messages · last activity 7/12/2026
Vite's HMR (Hot Module Replacement) system is a real-time update mechanism that allows changes during development to be reflected in the browser without a full page reload. Here's how it works:
Core Components
WebSocket Connection: The system establishes a WebSocket connection between the client and dev server. In [packages/vite/src/client/client.ts:L41-L80], the client creates a WebSocket transport with fallback logic:
let wsTransport = createWebSocketModuleRunnerTransport({
createConnection: () =>
new WebSocket(
`${socketProtocol}://${socketHost}?token=${wsToken}`,
'vite-hmr',
),
pingInterval: hmrTimeout,
})
If the initial connection fails and no explicit HMR port is configured, it attempts a fallback connection to a direct socket host.
Message Handling
The client processes incoming HMR payloads via the handleMessage function [packages/vite/src/client/client.ts:L206-L245]. When an update arrives:
- Connected: The client acknowledges the connection
- JS Updates: JavaScript modules are queued for replacement via
hmrClient.queueUpdate(update) - CSS Updates: CSS files are refreshed by finding their corresponding
<link>tags and updating the href with a timestamp query parameter to force a fresh fetch
Error Recovery
If an error overlay exists on the first update (indicating a prior server compile error), Vite performs a full location.reload() rather than attempting incremental HMR, since module dependencies may have failed to load.
Server Configuration
The server injects HMR configuration values into the client code [packages/vite/src/node/plugins/clientInjections.ts:L71-L143]. This includes:
- HMR hostname, port, protocol, and base path
- WebSocket timeout (default 30000ms)
- Error overlay settings
- A WebSocket token for security
Module Graph Integration
When CSS or JS dependencies are imported, Vite tracks them in the module graph [packages/vite/src/node/plugins/importAnalysis.ts:L385-L424], recording the lastHMRTimestamp so the browser can fetch the most up-to-date version via timestamped query parameters.
The Plugin API also provides a handleHotUpdate hook [packages/vite/src/node/plugin.ts:L341-L380] that allows plugins to customize HMR behavior by returning modified module nodes or sending custom HMR payloads.
FOLLOW_UPS:
- How does the module graph track dependencies?
- What's the purpose of the HMR error overlay?
- How do plugins customize HMR updates?
Want to ask your own question?
Open chat for vitejs/vitePublic Q&A. Generated by RepoPilot from the actual source of vitejs/vite. AI answers can be incomplete or stale — verify before relying on them.