0
# Hot Module Replacement
1
2
Complete HMR implementation with event handling, module invalidation, and hot context management for development workflows. Provides seamless hot reloading capabilities for Node.js applications during development.
3
4
## Capabilities
5
6
### HMR Context Management
7
8
Create and manage hot contexts for modules to handle hot updates.
9
10
```typescript { .api }
11
/**
12
* Create a hot context for a module to handle HMR updates
13
* Provides accept, dispose, and invalidate functionality
14
*/
15
function createHotContext(
16
runner: ViteNodeRunner,
17
emitter: HMREmitter,
18
files: string[],
19
ownerPath: string
20
): HotContext;
21
22
interface HotContext {
23
/** Module-specific data that persists across hot updates */
24
data: any;
25
26
/** Accept hot updates for this module or its dependencies */
27
accept(deps?: string | string[] | ((mod: any) => void), callback?: (mod: any) => void): void;
28
29
/** Accept updates for specific exports */
30
acceptExports(exports?: string | string[], callback?: (mod: any) => void): void;
31
32
/** Register cleanup function called before module is updated */
33
dispose(callback: (data: any) => void): void;
34
35
/** Register cleanup function called when module is pruned */
36
prune(callback: (data: any) => void): void;
37
38
/** Invalidate this module and trigger a full reload */
39
invalidate(): Promise<any[]>;
40
41
/** Listen for custom HMR events */
42
on<T extends string>(event: T, callback: (payload: any) => void): void;
43
44
/** Remove listener for custom HMR events */
45
off<T extends string>(event: T, callback: (payload: any) => void): void;
46
47
/** Send custom HMR event */
48
send<T extends string>(event: T, data?: any): void;
49
}
50
```
51
52
**Usage Examples:**
53
54
```typescript
55
// In a module that needs HMR support
56
if (import.meta.hot) {
57
import.meta.hot.accept((newModule) => {
58
// Handle hot update
59
console.log('Module updated', newModule);
60
});
61
62
import.meta.hot.dispose((data) => {
63
// Clean up before update
64
data.cleanup?.();
65
});
66
67
import.meta.hot.on('custom-event', (data) => {
68
// Handle custom HMR events
69
console.log('Custom event received', data);
70
});
71
}
72
```
73
74
### HMR Message Handling
75
76
Handle HMR messages and coordinate updates across the system.
77
78
```typescript { .api }
79
/**
80
* Handle HMR messages from Vite and coordinate appropriate responses
81
* Supports update, full-reload, error, and custom message types
82
*/
83
function handleMessage(
84
runner: ViteNodeRunner,
85
emitter: HMREmitter,
86
files: string[],
87
payload: HMRPayload
88
): Promise<void>;
89
```
90
91
**Usage Examples:**
92
93
```typescript
94
import { handleMessage } from "vite-node/hmr";
95
96
// Set up HMR message handling
97
server.emitter?.on('message', (payload) => {
98
handleMessage(runner, server.emitter, files, payload);
99
});
100
```
101
102
### Module Reloading
103
104
Reload modules and handle cache invalidation during hot updates.
105
106
```typescript { .api }
107
/**
108
* Reload specified files and invalidate their cache entries
109
* Preserves node_modules cache while clearing application modules
110
*/
111
function reload(runner: ViteNodeRunner, files: string[]): Promise<any[]>;
112
```
113
114
**Usage Examples:**
115
116
```typescript
117
import { reload } from "vite-node/hmr";
118
119
// Reload specific files
120
const results = await reload(runner, ['./src/app.ts', './src/utils.ts']);
121
122
// Handle reload results
123
results.forEach((result, index) => {
124
console.log(`Reloaded ${files[index]}:`, result);
125
});
126
```
127
128
### HMR Cache Management
129
130
Access and manage HMR-related cache data.
131
132
```typescript { .api }
133
/**
134
* Get HMR cache data for a runner instance
135
* Includes hot modules, data, dispose callbacks, and message buffers
136
*/
137
function getCache(runner: ViteNodeRunner): CacheData;
138
139
interface CacheData {
140
hotModulesMap: Map<string, HotModule>;
141
dataMap: Map<string, any>;
142
disposeMap: Map<string, (data: any) => void | Promise<void>>;
143
pruneMap: Map<string, (data: any) => void | Promise<void>>;
144
customListenersMap: Map<string, ((data: any) => void)[]>;
145
ctxToListenersMap: Map<string, Map<string, ((data: any) => void)[]>>;
146
messageBuffer: string[];
147
isFirstUpdate: boolean;
148
pending: boolean;
149
queued: Promise<(() => void) | undefined>[];
150
}
151
152
interface HotModule {
153
id: string;
154
callbacks: HotCallback[];
155
}
156
157
interface HotCallback {
158
deps: string[];
159
fn: (modules: (ModuleNamespace | undefined)[]) => void;
160
}
161
```
162
163
### Message Buffer Management
164
165
Manage buffered HMR messages for reliable delivery.
166
167
```typescript { .api }
168
/**
169
* Send buffered messages to HMR emitter
170
* Ensures messages are delivered even if connection is temporarily unavailable
171
*/
172
function sendMessageBuffer(runner: ViteNodeRunner, emitter: HMREmitter): void;
173
```
174
175
### HMR Emitter
176
177
Event emitter for HMR communication between server and clients.
178
179
```typescript { .api }
180
/**
181
* Create HMR emitter for handling hot update events
182
* Extends EventEmitter with HMR-specific message handling
183
*/
184
function createHmrEmitter(): HMREmitter;
185
186
interface HMREmitter extends EventEmitter {
187
on(event: 'message', handler: (payload: HMRPayload) => void): void;
188
emit(event: 'message', payload: HMRPayload): void;
189
}
190
```
191
192
### Vite Plugin Integration
193
194
Vite plugin for integrating HMR functionality.
195
196
```typescript { .api }
197
/**
198
* Vite plugin that enables HMR functionality for vite-node
199
* Configures server settings and message handling
200
*/
201
function viteNodeHmrPlugin(): Plugin;
202
```
203
204
**Usage Examples:**
205
206
```typescript
207
import { viteNodeHmrPlugin } from "vite-node/hmr";
208
209
const server = await createServer({
210
plugins: [
211
viteNodeHmrPlugin(),
212
// other plugins...
213
],
214
});
215
```
216
217
## HMR Event Types
218
219
HMR supports various event types for different update scenarios:
220
221
### Connected Event
222
Triggered when HMR connection is established.
223
224
### Update Event
225
Handles JavaScript module updates with dependency tracking.
226
227
### Full Reload Event
228
Triggers complete application reload when necessary.
229
230
### Custom Event
231
Supports custom application-specific HMR events.
232
233
### Prune Event
234
Handles cleanup when modules are removed.
235
236
### Error Event
237
Handles and displays HMR-related errors.
238
239
## Usage Patterns
240
241
### Basic HMR Setup
242
243
```typescript
244
import { createServer } from "vite";
245
import { ViteNodeRunner } from "vite-node/client";
246
import { ViteNodeServer } from "vite-node/server";
247
import { createHotContext, handleMessage, viteNodeHmrPlugin } from "vite-node/hmr";
248
249
// Create Vite server with HMR support
250
const server = await createServer({
251
plugins: [viteNodeHmrPlugin()],
252
server: { hmr: true },
253
});
254
255
// Create vite-node components
256
const nodeServer = new ViteNodeServer(server);
257
const runner = new ViteNodeRunner({
258
root: server.config.root,
259
fetchModule: (id) => nodeServer.fetchModule(id),
260
resolveId: (id, importer) => nodeServer.resolveId(id, importer),
261
createHotContext: (runner, url) => createHotContext(runner, server.emitter, files, url),
262
});
263
264
// Handle HMR messages
265
server.emitter?.on('message', (payload) => {
266
handleMessage(runner, server.emitter, files, payload);
267
});
268
```
269
270
### Module-level HMR
271
272
```typescript
273
// In your application modules
274
declare global {
275
interface ImportMeta {
276
hot?: {
277
accept: (callback?: (newModule: any) => void) => void;
278
dispose: (callback: (data: any) => void) => void;
279
data: any;
280
};
281
}
282
}
283
284
// Use HMR in modules
285
if (import.meta.hot) {
286
// Accept updates to this module
287
import.meta.hot.accept((newModule) => {
288
console.log('Module hot updated');
289
});
290
291
// Cleanup before update
292
import.meta.hot.dispose((data) => {
293
// Store state for next version
294
data.state = getCurrentState();
295
});
296
297
// Access preserved data
298
const previousState = import.meta.hot.data.state;
299
}
300
```
301
302
## Error Handling
303
304
HMR includes comprehensive error handling:
305
306
- **Update Failures**: Graceful handling when hot updates fail
307
- **Connection Issues**: Automatic reconnection and message buffering
308
- **Module Errors**: Clear error reporting with source maps
309
- **Circular Dependencies**: Detection and safe handling
310
311
Common error handling patterns:
312
313
```typescript
314
// Handle HMR errors
315
server.emitter?.on('message', async (payload) => {
316
try {
317
await handleMessage(runner, server.emitter, files, payload);
318
} catch (error) {
319
console.error('HMR update failed:', error);
320
// Optionally trigger full reload
321
await reload(runner, files);
322
}
323
});
324
```
325
326
## Performance Considerations
327
328
HMR is optimized for development performance:
329
330
- **Incremental Updates**: Only affected modules are reloaded
331
- **Dependency Tracking**: Smart invalidation of dependent modules
332
- **Message Buffering**: Prevents loss of updates during brief disconnections
333
- **Lazy Evaluation**: Updates are queued and batched for efficiency