0
# Runtime Utilities
1
2
React Refresh runtime utilities that handle module boundary detection, component registration, and hot reload coordination at runtime.
3
4
## Capabilities
5
6
### Enqueue Update
7
8
Schedules a React Refresh update to be processed during the next update cycle.
9
10
```javascript { .api }
11
/**
12
* Enqueues a React component update for processing
13
* @returns {void}
14
*/
15
function enqueueUpdate(): void;
16
```
17
18
**Usage Example:**
19
20
```javascript
21
const RefreshUtils = require('@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils');
22
23
// Trigger a refresh update
24
RefreshUtils.enqueueUpdate();
25
```
26
27
### Execute Runtime
28
29
Executes the React Refresh runtime, processing any pending updates and refreshing affected components.
30
31
```javascript { .api }
32
/**
33
* Executes the React Refresh runtime to process pending updates
34
* @returns {void}
35
*/
36
function executeRuntime(): void;
37
```
38
39
**Usage Example:**
40
41
```javascript
42
const RefreshUtils = require('@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils');
43
44
// Execute runtime after module updates
45
RefreshUtils.executeRuntime();
46
```
47
48
### Get Module Exports
49
50
Retrieves the current exports of a webpack module by its ID.
51
52
```javascript { .api }
53
/**
54
* Gets the current exports of a webpack module
55
* @param {string} moduleId - The webpack module identifier
56
* @returns {any} - The module's current exports
57
*/
58
function getModuleExports(moduleId: string): any;
59
```
60
61
**Usage Example:**
62
63
```javascript
64
const RefreshUtils = require('@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils');
65
66
// Get module exports for inspection
67
const moduleExports = RefreshUtils.getModuleExports('./src/components/Button.jsx');
68
console.log('Button component exports:', moduleExports);
69
```
70
71
### Is React Refresh Boundary
72
73
Determines whether a module's exports constitute a valid React Refresh boundary (i.e., contains React components).
74
75
```javascript { .api }
76
/**
77
* Checks if module exports represent a React Refresh boundary
78
* @param {any} moduleExports - The exports to check
79
* @returns {boolean} - True if exports form a valid refresh boundary
80
*/
81
function isReactRefreshBoundary(moduleExports: any): boolean;
82
```
83
84
**Usage Example:**
85
86
```javascript
87
const RefreshUtils = require('@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils');
88
89
// Check if a module is a React component boundary
90
const ButtonExports = require('./Button.jsx');
91
const isRefreshable = RefreshUtils.isReactRefreshBoundary(ButtonExports);
92
93
console.log('Button is refreshable:', isRefreshable);
94
95
// Non-React modules return false
96
const utilsExports = require('./utils.js');
97
const isUtilsRefreshable = RefreshUtils.isReactRefreshBoundary(utilsExports);
98
console.log('Utils is refreshable:', isUtilsRefreshable); // false
99
```
100
101
### Register Exports For React Refresh
102
103
Registers a module's exports with the React Refresh runtime for hot reloading.
104
105
```javascript { .api }
106
/**
107
* Registers module exports with React Refresh runtime
108
* @param {string} moduleId - The webpack module identifier
109
* @param {any} moduleExports - The module's exports to register
110
* @returns {void}
111
*/
112
function registerExportsForReactRefresh(moduleId: string, moduleExports: any): void;
113
```
114
115
**Usage Example:**
116
117
```javascript
118
const RefreshUtils = require('@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils');
119
120
// Register React component for refresh
121
const MyComponent = require('./MyComponent.jsx');
122
RefreshUtils.registerExportsForReactRefresh('./src/MyComponent.jsx', MyComponent);
123
124
// Typically used in module hot accept callbacks
125
if (module.hot) {
126
module.hot.accept('./MyComponent.jsx', () => {
127
const UpdatedComponent = require('./MyComponent.jsx');
128
RefreshUtils.registerExportsForReactRefresh('./src/MyComponent.jsx', UpdatedComponent);
129
RefreshUtils.enqueueUpdate();
130
});
131
}
132
```
133
134
## Advanced Usage Patterns
135
136
### Custom Module Hot Reload Logic
137
138
Implement custom hot reload logic using runtime utilities:
139
140
```javascript
141
const RefreshUtils = require('@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils');
142
143
function handleModuleUpdate(moduleId, newExports) {
144
// Check if module can be hot reloaded
145
if (RefreshUtils.isReactRefreshBoundary(newExports)) {
146
console.log(`Module ${moduleId} is refreshable`);
147
148
// Register updated exports
149
RefreshUtils.registerExportsForReactRefresh(moduleId, newExports);
150
151
// Trigger refresh
152
RefreshUtils.enqueueUpdate();
153
RefreshUtils.executeRuntime();
154
} else {
155
console.log(`Module ${moduleId} requires full reload`);
156
window.location.reload();
157
}
158
}
159
160
// Usage in webpack HMR accept callback
161
if (module.hot) {
162
module.hot.accept(['./ComponentA.jsx', './ComponentB.jsx'], (updatedDependencies) => {
163
updatedDependencies.forEach(moduleId => {
164
const newExports = RefreshUtils.getModuleExports(moduleId);
165
handleModuleUpdate(moduleId, newExports);
166
});
167
});
168
}
169
```
170
171
### Component Boundary Detection
172
173
Detect and categorize different types of module exports:
174
175
```javascript
176
const RefreshUtils = require('@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils');
177
178
function categorizeModule(moduleExports, moduleId) {
179
if (RefreshUtils.isReactRefreshBoundary(moduleExports)) {
180
return {
181
type: 'react-component',
182
refreshable: true,
183
moduleId,
184
exports: moduleExports
185
};
186
}
187
188
// Check for higher-order components or hooks
189
if (typeof moduleExports === 'function' && moduleExports.name.startsWith('use')) {
190
return {
191
type: 'react-hook',
192
refreshable: true, // Hooks can be refreshed
193
moduleId,
194
exports: moduleExports
195
};
196
}
197
198
return {
199
type: 'utility',
200
refreshable: false,
201
moduleId,
202
exports: moduleExports
203
};
204
}
205
206
// Categorize current module
207
const moduleInfo = categorizeModule(module.exports, module.id);
208
console.log('Module info:', moduleInfo);
209
210
if (moduleInfo.refreshable) {
211
RefreshUtils.registerExportsForReactRefresh(moduleInfo.moduleId, moduleInfo.exports);
212
}
213
```
214
215
### Batch Update Processing
216
217
Process multiple module updates efficiently:
218
219
```javascript
220
const RefreshUtils = require('@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils');
221
222
class RefreshBatchProcessor {
223
constructor() {
224
this.pendingUpdates = new Set();
225
this.processingTimeout = null;
226
}
227
228
addUpdate(moduleId, moduleExports) {
229
// Register the module
230
if (RefreshUtils.isReactRefreshBoundary(moduleExports)) {
231
RefreshUtils.registerExportsForReactRefresh(moduleId, moduleExports);
232
this.pendingUpdates.add(moduleId);
233
234
// Schedule batch processing
235
this.scheduleBatchProcess();
236
}
237
}
238
239
scheduleBatchProcess() {
240
if (this.processingTimeout) {
241
clearTimeout(this.processingTimeout);
242
}
243
244
this.processingTimeout = setTimeout(() => {
245
this.processBatch();
246
}, 10); // Small delay to batch multiple updates
247
}
248
249
processBatch() {
250
if (this.pendingUpdates.size > 0) {
251
console.log(`Processing ${this.pendingUpdates.size} pending updates`);
252
253
// Single enqueue and execute for all updates
254
RefreshUtils.enqueueUpdate();
255
RefreshUtils.executeRuntime();
256
257
this.pendingUpdates.clear();
258
}
259
this.processingTimeout = null;
260
}
261
}
262
263
// Global batch processor
264
const batchProcessor = new RefreshBatchProcessor();
265
266
// Use in HMR callbacks
267
if (module.hot) {
268
module.hot.accept(['./ComponentA.jsx', './ComponentB.jsx'], () => {
269
const ComponentA = RefreshUtils.getModuleExports('./ComponentA.jsx');
270
const ComponentB = RefreshUtils.getModuleExports('./ComponentB.jsx');
271
272
batchProcessor.addUpdate('./ComponentA.jsx', ComponentA);
273
batchProcessor.addUpdate('./ComponentB.jsx', ComponentB);
274
});
275
}
276
```
277
278
## Runtime Integration
279
280
These utilities are typically used by the webpack loader and runtime modules automatically, but can be used directly for advanced customization:
281
282
```javascript
283
// Custom loader or plugin integration
284
const RefreshUtils = require('@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils');
285
286
// In a custom webpack loader
287
module.exports = function customReactLoader(source) {
288
if (this.mode === 'development') {
289
// Add runtime registration code
290
const refreshCode = `
291
const RefreshUtils = require('@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils');
292
293
if (RefreshUtils.isReactRefreshBoundary(module.exports)) {
294
RefreshUtils.registerExportsForReactRefresh(module.id, module.exports);
295
296
if (module.hot) {
297
module.hot.accept(() => {
298
RefreshUtils.enqueueUpdate();
299
RefreshUtils.executeRuntime();
300
});
301
}
302
}
303
`;
304
305
return source + '\n\n' + refreshCode;
306
}
307
308
return source;
309
};
310
```