RepoPilot

How does Vite's HMR system work?

About vitejs/vite · 2 messages · last activity 7/12/2026

Question

How does Vite's HMR system work?

RepoPilot

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:

  1. Connected: The client acknowledges the connection
  2. JS Updates: JavaScript modules are queued for replacement via hmrClient.queueUpdate(update)
  3. 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/vite

Public Q&A. Generated by RepoPilot from the actual source of vitejs/vite. AI answers can be incomplete or stale — verify before relying on them.