or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli.mdclient.mdhmr.mdindex.mdserver.mdsource-maps.mdutils.md

hmr.mddocs/

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