or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdcore-bundling.mdhmr.mdindex.mdloaders.mdmodule-federation.mdplugins.md

hmr.mddocs/

0

# Hot Module Replacement

1

2

Development-time module replacement system for fast iteration without losing application state, with full webpack compatibility.

3

4

## Capabilities

5

6

### Core HMR Interface

7

8

The main HMR API exposed through `module.hot` when HMR is enabled.

9

10

```typescript { .api }

11

interface Hot {

12

/** Accept module updates with optional callback and error handling */

13

accept: {

14

/** Accept specific modules with callback for handling updates */

15

(

16

modules: string | string[],

17

callback?: (outdatedDependencies: string[]) => void,

18

errorHandler?: (

19

err: Error,

20

context: { moduleId: string | number; dependencyId: string | number }

21

) => void

22

): void;

23

24

/** Accept self updates with error handling */

25

(

26

errorHandler?: (

27

err: Error,

28

ids: { moduleId: string | number; module: NodeJS.Module }

29

) => void

30

): void;

31

};

32

33

/** Get current HMR status */

34

status(): HotUpdateStatus;

35

36

/** Decline updates for specific modules */

37

decline(module?: string | string[]): void;

38

39

/** Register callback for module disposal */

40

dispose(callback: (data: any) => void): void;

41

42

/** Add disposal handler */

43

addDisposeHandler(callback: (data: any) => void): void;

44

45

/** Remove disposal handler */

46

removeDisposeHandler(callback: (data: any) => void): void;

47

48

/** Invalidate current module */

49

invalidate(): void;

50

51

/** Add status change handler */

52

addStatusHandler(callback: (status: HotUpdateStatus) => void): void;

53

54

/** Remove status change handler */

55

removeStatusHandler(callback: (status: HotUpdateStatus) => void): void;

56

57

/** Data storage between updates */

58

data: any;

59

60

/** Check for available updates */

61

check(autoApply?: boolean | ApplyOptions): Promise<(string | number)[] | null>;

62

63

/** Apply pending updates */

64

apply(options?: ApplyOptions): Promise<(string | number)[] | null>;

65

}

66

67

/** HMR status values indicating current state */

68

type HotUpdateStatus = "idle" | "check" | "prepare" | "ready" | "dispose" | "apply" | "abort" | "fail";

69

```

70

71

**Usage Examples:**

72

73

```typescript

74

// Basic self-acceptance

75

if (module.hot) {

76

module.hot.accept((err) => {

77

if (err) {

78

console.error("Cannot accept update:", err);

79

}

80

});

81

}

82

83

// Accept specific dependencies

84

if (module.hot) {

85

module.hot.accept("./utils", (outdatedDependencies) => {

86

console.log("Utils module updated:", outdatedDependencies);

87

// Re-import and use updated utils

88

import("./utils").then((newUtils) => {

89

// Update application state with new utils

90

});

91

});

92

}

93

94

// Accept multiple dependencies with error handling

95

if (module.hot) {

96

module.hot.accept(

97

["./component-a", "./component-b"],

98

(outdatedDependencies) => {

99

console.log("Components updated:", outdatedDependencies);

100

},

101

(err, context) => {

102

console.error("Update failed:", err, context);

103

}

104

);

105

}

106

107

// Data persistence across updates

108

if (module.hot) {

109

// Save state before disposal

110

module.hot.dispose((data) => {

111

data.currentUser = getCurrentUser();

112

data.preferences = getPreferences();

113

});

114

115

// Restore state after update

116

if (module.hot.data) {

117

setCurrentUser(module.hot.data.currentUser);

118

setPreferences(module.hot.data.preferences);

119

}

120

}

121

122

// Status monitoring

123

if (module.hot) {

124

module.hot.addStatusHandler((status) => {

125

console.log("HMR Status:", status);

126

127

if (status === "apply") {

128

console.log("Applying updates...");

129

} else if (status === "fail") {

130

console.error("HMR update failed");

131

}

132

});

133

}

134

```

135

136

### HMR Configuration Options

137

138

Options for controlling update application behavior.

139

140

```typescript { .api }

141

interface ApplyOptions {

142

/** Ignore modules that declined the update */

143

ignoreUnaccepted?: boolean;

144

/** Ignore modules that were declined by dependencies */

145

ignoreDeclined?: boolean;

146

/** Ignore modules that errored during update */

147

ignoreErrored?: boolean;

148

/** Handler for declined events */

149

onDeclined?: (event: DeclinedEvent) => void;

150

/** Handler for unaccepted events */

151

onUnaccepted?: (event: UnacceptedEvent) => void;

152

/** Handler for accepted events */

153

onAccepted?: (event: AcceptedEvent) => void;

154

/** Handler for disposed events */

155

onDisposed?: (event: DisposedEvent) => void;

156

/** Handler for error events */

157

onErrored?: (event: ErroredEvent) => void;

158

}

159

```

160

161

### HMR Event Types

162

163

Detailed event types for different HMR scenarios.

164

165

```typescript { .api }

166

/** Module update was successfully accepted */

167

interface AcceptedEvent {

168

type: "accepted";

169

/** The module that was updated */

170

moduleId: string | number;

171

/** Modules that became outdated */

172

outdatedModules: (string | number)[];

173

/** Dependencies that became outdated */

174

outdatedDependencies: { [id: number]: (string | number)[] };

175

}

176

177

/** Module update was declined */

178

type DeclinedEvent =

179

| {

180

type: "declined";

181

/** The module in question */

182

moduleId: string | number;

183

/** Update propagation chain */

184

chain: (string | number)[];

185

/** Module that declined the update */

186

parentId: string | number;

187

}

188

| {

189

type: "self-declined";

190

/** The module in question */

191

moduleId: string | number;

192

/** Update propagation chain */

193

chain: (string | number)[];

194

};

195

196

/** Module update was not accepted */

197

interface UnacceptedEvent {

198

type: "unaccepted";

199

/** The module in question */

200

moduleId: string | number;

201

/** Update propagation chain */

202

chain: (string | number)[];

203

}

204

205

/** Module was disposed */

206

interface DisposedEvent {

207

type: "disposed";

208

/** The module that was disposed */

209

moduleId: string | number;

210

}

211

212

/** Error occurred during HMR process */

213

type ErroredEvent =

214

| {

215

type: "accept-error-handler-errored";

216

/** The module in question */

217

moduleId: string | number;

218

/** Module owning the error handler */

219

dependencyId: string | number;

220

/** The error that occurred */

221

error: Error;

222

/** Original error that triggered the handler */

223

originalError: Error;

224

}

225

| {

226

type: "self-accept-error-handler-errored";

227

/** The module in question */

228

moduleId: string | number;

229

/** The error that occurred */

230

error: Error;

231

/** Original error that triggered the handler */

232

originalError: Error;

233

}

234

| {

235

type: "accept-errored";

236

/** The module in question */

237

moduleId: string | number;

238

/** Module owning the accept handler */

239

dependencyId: string | number;

240

/** The error that occurred */

241

error: Error;

242

}

243

| {

244

type: "self-accept-errored";

245

/** The module in question */

246

moduleId: string | number;

247

/** The error that occurred */

248

error: Error;

249

};

250

251

/** Union of all HMR event types */

252

type HotEvent = AcceptedEvent | DeclinedEvent | UnacceptedEvent | DisposedEvent | ErroredEvent;

253

```

254

255

### ES Modules HMR Support

256

257

HMR support for ES modules via `import.meta`.

258

259

```typescript { .api }

260

interface ImportMeta {

261

/** HMR interface for ES modules (same as module.hot) */

262

webpackHot: Hot;

263

/** Base URL of the module */

264

url: string;

265

/** Webpack context function */

266

webpackContext: (

267

request: string,

268

options?: {

269

recursive?: boolean;

270

regExp?: RegExp;

271

include?: RegExp;

272

exclude?: RegExp;

273

preload?: boolean | number;

274

prefetch?: boolean | number;

275

fetchPriority?: "low" | "high" | "auto";

276

chunkName?: string;

277

exports?: string | string[][];

278

mode?: "sync" | "eager" | "weak" | "lazy" | "lazy-once";

279

}

280

) => any;

281

}

282

```

283

284

**ES Modules Usage:**

285

286

```typescript

287

// ES modules HMR

288

if (import.meta.webpackHot) {

289

import.meta.webpackHot.accept("./dependency", () => {

290

console.log("Dependency hot-reloaded");

291

});

292

}

293

```

294

295

### HMR Client Runtime

296

297

Client-side runtime files for different HMR integration scenarios.

298

299

```typescript { .api }

300

/** WebSocket-based HMR client for webpack-dev-server */

301

declare module "@rspack/core/hot/dev-server" {

302

// Automatically connects to dev server

303

}

304

305

/** Enhanced dev-server client with better error handling */

306

declare module "@rspack/core/hot/only-dev-server" {

307

// Only hot reloads, no page refresh on errors

308

}

309

310

/** Polling-based HMR client */

311

declare module "@rspack/core/hot/poll" {

312

// Polls for updates periodically

313

}

314

315

/** Signal-based HMR client for Node.js */

316

declare module "@rspack/core/hot/signal" {

317

// Uses process signals for updates

318

}

319

320

/** HMR logging utility */

321

declare module "@rspack/core/hot/log" {

322

export function setLogLevel(level: "info" | "warning" | "error" | "none"): void;

323

export function info(...args: any[]): void;

324

export function warning(...args: any[]): void;

325

export function error(...args: any[]): void;

326

}

327

328

/** Event emitter for HMR events */

329

declare module "@rspack/core/hot/emitter" {

330

interface EventEmitter {

331

on(event: string, listener: (...args: any[]) => void): this;

332

emit(event: string, ...args: any[]): boolean;

333

}

334

335

const emitter: EventEmitter;

336

export default emitter;

337

}

338

```

339

340

### HMR Plugin Configuration

341

342

Plugin for enabling Hot Module Replacement.

343

344

```typescript { .api }

345

/** Enable HMR functionality */

346

class HotModuleReplacementPlugin extends RspackBuiltinPlugin {

347

name: "HotModuleReplacementPlugin";

348

/** No configuration options needed */

349

constructor();

350

}

351

```

352

353

**Plugin Usage:**

354

355

```typescript

356

import { HotModuleReplacementPlugin } from "@rspack/core";

357

358

const config = {

359

mode: "development",

360

devServer: {

361

hot: true

362

},

363

plugins: [

364

new HotModuleReplacementPlugin()

365

]

366

};

367

```

368

369

### Advanced HMR Patterns

370

371

Common patterns for effective HMR integration.

372

373

```typescript

374

// React component HMR

375

if (module.hot) {

376

module.hot.accept("./App", () => {

377

const NextApp = require("./App").default;

378

render(<NextApp />, document.getElementById("root"));

379

});

380

}

381

382

// Redux store HMR

383

if (module.hot) {

384

module.hot.accept("./reducers", () => {

385

const nextRootReducer = require("./reducers").default;

386

store.replaceReducer(nextRootReducer);

387

});

388

}

389

390

// CSS HMR with extraction

391

if (module.hot) {

392

module.hot.accept("./styles.css", () => {

393

// CSS is automatically reloaded by CssExtractRspackPlugin

394

});

395

}

396

397

// Manual update checking

398

if (module.hot) {

399

const checkForUpdates = async () => {

400

try {

401

const outdatedModules = await module.hot.check(false);

402

if (outdatedModules) {

403

console.log("Updates available:", outdatedModules);

404

const result = await module.hot.apply({

405

ignoreUnaccepted: true,

406

onAccepted: (event) => {

407

console.log("Module accepted:", event.moduleId);

408

}

409

});

410

console.log("Updates applied:", result);

411

}

412

} catch (err) {

413

console.error("Update failed:", err);

414

}

415

};

416

417

// Check for updates every 10 seconds

418

setInterval(checkForUpdates, 10000);

419

}

420

```