or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

build-system.mdconfiguration.mdcss-processing.mddev-server.mdhmr.mdindex.mdmodule-resolution.mdplugin-system.mdssr.mdutilities.md

hmr.mddocs/

0

# Hot Module Replacement

1

2

Vite's Hot Module Replacement (HMR) system provides instant updates during development with WebSocket communication, client-server coordination, and comprehensive plugin integration for seamless development experience.

3

4

## Capabilities

5

6

### Server Hot Channel

7

8

Create server-side HMR channel for communication with clients.

9

10

```typescript { .api }

11

/**

12

* Create server hot channel for HMR communication

13

* @param server - Vite dev server (optional)

14

* @returns ServerHotChannel instance

15

*/

16

function createServerHotChannel(server?: ViteDevServer): ServerHotChannel;

17

18

interface ServerHotChannel extends HotChannel {

19

/** Send update to all clients */

20

send(payload: HotPayload): void;

21

/** Close channel */

22

close(): void;

23

/** Handle client connection */

24

on(event: 'connection', handler: (client: HotChannelClient) => void): void;

25

/** Handle client disconnect */

26

on(event: 'disconnect', handler: (client: HotChannelClient) => void): void;

27

}

28

```

29

30

**Usage Examples:**

31

32

```typescript

33

import { createServerHotChannel } from "vite";

34

35

// Create HMR channel

36

const hotChannel = createServerHotChannel(server);

37

38

// Send custom update

39

hotChannel.send({

40

type: 'custom',

41

event: 'my-plugin-update',

42

data: { message: 'Plugin state changed' }

43

});

44

45

// Listen for connections

46

hotChannel.on('connection', (client) => {

47

console.log('Client connected:', client.socket.id);

48

});

49

```

50

51

### HMR Configuration

52

53

Configure Hot Module Replacement behavior and WebSocket settings.

54

55

```typescript { .api }

56

interface HmrOptions {

57

/** HMR port (default: 24678) */

58

port?: number;

59

/** HMR host */

60

host?: string;

61

/** Client-side port override */

62

clientPort?: number;

63

/** Show error overlay */

64

overlay?: boolean;

65

/** HMR server */

66

server?: any;

67

}

68

69

interface HotUpdateOptions {

70

/** Update type */

71

type: 'js-update' | 'css-update' | 'full-reload';

72

/** Timestamp */

73

timestamp?: number;

74

/** Updates to apply */

75

updates?: Update[];

76

}

77

```

78

79

### HMR Payload Types

80

81

Types for different HMR messages sent between server and client.

82

83

```typescript { .api }

84

/**

85

* Union of all possible HMR payloads

86

*/

87

type HotPayload =

88

| ConnectedPayload

89

| UpdatePayload

90

| FullReloadPayload

91

| PrunePayload

92

| ErrorPayload

93

| CustomPayload;

94

95

interface ConnectedPayload {

96

type: 'connected';

97

}

98

99

interface UpdatePayload {

100

type: 'update';

101

updates: Update[];

102

}

103

104

interface Update {

105

/** Update type */

106

type: 'js-update' | 'css-update';

107

/** Module path */

108

path: string;

109

/** Update timestamp */

110

timestamp: number;

111

/** Accepted modules */

112

acceptedPath: string;

113

/** Explicit imports only */

114

explicitImportRequired?: boolean;

115

/** SSR error */

116

ssrError?: Error;

117

}

118

119

interface FullReloadPayload {

120

type: 'full-reload';

121

/** Reload trigger path */

122

path?: string;

123

}

124

125

interface PrunePayload {

126

type: 'prune';

127

/** Paths to prune */

128

paths: string[];

129

}

130

131

interface ErrorPayload {

132

type: 'error';

133

/** Error details */

134

err: {

135

message: string;

136

stack: string;

137

id?: string;

138

frame?: string;

139

plugin?: string;

140

pluginCode?: string;

141

loc?: {

142

file?: string;

143

line: number;

144

column: number;

145

};

146

};

147

}

148

149

interface CustomPayload {

150

type: 'custom';

151

/** Custom event name */

152

event: string;

153

/** Custom data */

154

data?: any;

155

}

156

```

157

158

**Usage Examples:**

159

160

```typescript

161

// Send different types of updates

162

const hotChannel = createServerHotChannel();

163

164

// JavaScript update

165

hotChannel.send({

166

type: 'update',

167

updates: [{

168

type: 'js-update',

169

path: '/src/components/Button.tsx',

170

timestamp: Date.now(),

171

acceptedPath: '/src/components/Button.tsx'

172

}]

173

});

174

175

// CSS update

176

hotChannel.send({

177

type: 'update',

178

updates: [{

179

type: 'css-update',

180

path: '/src/styles/main.css',

181

timestamp: Date.now(),

182

acceptedPath: '/src/styles/main.css'

183

}]

184

});

185

186

// Full reload

187

hotChannel.send({

188

type: 'full-reload',

189

path: '/vite.config.js'

190

});

191

192

// Custom event

193

hotChannel.send({

194

type: 'custom',

195

event: 'config-changed',

196

data: { newConfig: {...} }

197

});

198

```

199

200

### HMR Context

201

202

Context information provided to HMR handlers during hot updates.

203

204

```typescript { .api }

205

interface HmrContext {

206

/** File that changed */

207

file: string;

208

/** Change timestamp */

209

timestamp: number;

210

/** Affected module nodes */

211

modules: Set<ModuleNode>;

212

/** Read file contents */

213

read: () => string | Promise<string>;

214

/** Vite dev server */

215

server: ViteDevServer;

216

}

217

```

218

219

### WebSocket Server

220

221

WebSocket server interface for HMR communication.

222

223

```typescript { .api }

224

interface WebSocketServer {

225

/** Send message to all clients */

226

send(payload: HotPayload): void;

227

/** Send message to specific client */

228

send(client: WebSocketClient, payload: HotPayload): void;

229

/** Close server */

230

close(): Promise<void>;

231

/** Handle client connections */

232

on(event: 'connection', handler: (socket: WebSocketClient, request: any) => void): void;

233

/** Handle errors */

234

on(event: 'error', handler: (error: Error) => void): void;

235

}

236

237

interface WebSocketClient {

238

/** Send message to client */

239

send(data: string): void;

240

/** Close client connection */

241

close(): void;

242

/** Terminate connection */

243

terminate(): void;

244

/** Connection state */

245

readyState: number;

246

/** Client socket */

247

socket: any;

248

/** Handle messages */

249

on(event: 'message', handler: (data: any) => void): void;

250

/** Handle close */

251

on(event: 'close', handler: () => void): void;

252

/** Handle errors */

253

on(event: 'error', handler: (error: Error) => void): void;

254

}

255

256

interface WebSocketCustomListener<T = any> {

257

(data: T, client: WebSocketClient): void;

258

}

259

```

260

261

### Hot Channel Types

262

263

Normalized hot channel interfaces for consistent HMR communication.

264

265

```typescript { .api }

266

interface HotChannel {

267

/** Listen for events */

268

on(event: string, handler: HotChannelListener): void;

269

/** Remove event listener */

270

off(event: string, handler: HotChannelListener): void;

271

/** Send data */

272

send(data: any): void;

273

}

274

275

interface HotChannelClient {

276

/** Send data to client */

277

send(data: any): void;

278

/** Close client connection */

279

close(): void;

280

/** Underlying socket */

281

socket: any;

282

}

283

284

interface NormalizedHotChannel extends HotChannel {

285

/** Send payload */

286

send(payload: HotPayload): void;

287

}

288

289

interface NormalizedHotChannelClient extends HotChannelClient {

290

/** Send payload to client */

291

send(payload: HotPayload): void;

292

}

293

294

interface NormalizedServerHotChannel extends ServerHotChannel {

295

/** Send to all clients */

296

send(payload: HotPayload): void;

297

/** Send to specific client */

298

send(client: NormalizedHotChannelClient, payload: HotPayload): void;

299

}

300

301

type HotChannelListener = (data: any, client?: HotChannelClient) => void;

302

```

303

304

## HMR Integration Patterns

305

306

### Plugin HMR Support

307

308

Integrate HMR support in plugins for custom file types.

309

310

```typescript { .api }

311

// Plugin with HMR support

312

function myPlugin(): Plugin {

313

return {

314

name: 'my-plugin',

315

load(id) {

316

if (id.endsWith('.myext')) {

317

// Load custom file type

318

return `export default ${JSON.stringify(loadMyFile(id))}`;

319

}

320

},

321

handleHotUpdate(ctx) {

322

if (ctx.file.endsWith('.myext')) {

323

// Custom HMR logic for .myext files

324

ctx.server.ws.send({

325

type: 'custom',

326

event: 'myext-changed',

327

data: { file: ctx.file }

328

});

329

330

// Return empty array to prevent default HMR

331

return [];

332

}

333

}

334

};

335

}

336

```

337

338

### Client-Side HMR API

339

340

Client-side HMR API available in development.

341

342

```typescript { .api }

343

// Available in client code during development

344

interface ImportMeta {

345

hot?: {

346

/** Accept updates for this module */

347

accept(): void;

348

accept(cb: (newModule: any) => void): void;

349

accept(deps: string[], cb: (newModules: any[]) => void): void;

350

351

/** Decline updates for this module */

352

decline(): void;

353

354

/** Dispose callback when module is replaced */

355

dispose(cb: () => void): void;

356

357

/** Invalidate and force full reload */

358

invalidate(): void;

359

360

/** Register custom event listener */

361

on<T = any>(event: string, cb: (data: T) => void): void;

362

363

/** Send custom event to server */

364

send<T = any>(event: string, data?: T): void;

365

};

366

}

367

```

368

369

**Usage Examples:**

370

371

```typescript

372

// Component with HMR support

373

let count = 0;

374

375

export function Counter() {

376

return `<div>Count: ${count}</div>`;

377

}

378

379

// HMR boundary

380

if (import.meta.hot) {

381

import.meta.hot.accept((newModule) => {

382

// Handle module replacement

383

console.log('Counter updated');

384

});

385

386

import.meta.hot.dispose(() => {

387

// Cleanup before replacement

388

console.log('Cleaning up counter');

389

});

390

391

// Listen for custom events

392

import.meta.hot.on('reset-counter', () => {

393

count = 0;

394

updateUI();

395

});

396

}

397

```

398

399

### Error Handling

400

401

Handle HMR errors and recovery.

402

403

```typescript { .api }

404

// Error handling in plugins

405

function errorHandlingPlugin(): Plugin {

406

return {

407

name: 'error-handling',

408

handleHotUpdate(ctx) {

409

try {

410

// Process update

411

processUpdate(ctx.file);

412

} catch (error) {

413

// Send error to client

414

ctx.server.ws.send({

415

type: 'error',

416

err: {

417

message: error.message,

418

stack: error.stack,

419

id: ctx.file,

420

plugin: 'error-handling'

421

}

422

});

423

424

// Don't propagate error

425

return ctx.modules;

426

}

427

}

428

};

429

}

430

```