@rspack/plugin-react-refresh 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/reactRefresh.js +1 -1
- package/client/refreshUtils.js +297 -0
- package/dist/index.js +1 -3
- package/package.json +3 -6
package/client/reactRefresh.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
// Thanks https://github.com/pmmmwh/react-refresh-webpack-plugin
|
2
|
-
const RefreshUtils = require("
|
2
|
+
const RefreshUtils = require("./refreshUtils");
|
3
3
|
const RefreshRuntime = require("react-refresh/runtime");
|
4
4
|
|
5
5
|
// Port from https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/loader/utils/getRefreshModuleRuntime.js#L29
|
@@ -0,0 +1,297 @@
|
|
1
|
+
/**
|
2
|
+
* The following code is modified based on
|
3
|
+
* https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/0b960573797bf38926937994c481e4fec9ed8aa6/lib/runtime/RefreshUtils.js
|
4
|
+
*
|
5
|
+
* MIT Licensed
|
6
|
+
* Author Michael Mok
|
7
|
+
* Copyright (c) 2019 Michael Mok
|
8
|
+
* https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/0b960573797bf38926937994c481e4fec9ed8aa6/LICENSE
|
9
|
+
*/
|
10
|
+
|
11
|
+
/* global __webpack_require__ */
|
12
|
+
var Refresh = require("react-refresh/runtime");
|
13
|
+
|
14
|
+
/**
|
15
|
+
* Extracts exports from a webpack module object.
|
16
|
+
* @param {string} moduleId A Webpack module ID.
|
17
|
+
* @returns {*} An exports object from the module.
|
18
|
+
*/
|
19
|
+
function getModuleExports(moduleId) {
|
20
|
+
if (typeof moduleId === "undefined") {
|
21
|
+
// `moduleId` is unavailable, which indicates that this module is not in the cache,
|
22
|
+
// which means we won't be able to capture any exports,
|
23
|
+
// and thus they cannot be refreshed safely.
|
24
|
+
// These are likely runtime or dynamically generated modules.
|
25
|
+
return {};
|
26
|
+
}
|
27
|
+
|
28
|
+
var maybeModule = __webpack_require__.c[moduleId];
|
29
|
+
if (typeof maybeModule === "undefined") {
|
30
|
+
// `moduleId` is available but the module in cache is unavailable,
|
31
|
+
// which indicates the module is somehow corrupted (e.g. broken Webpacak `module` globals).
|
32
|
+
// We will warn the user (as this is likely a mistake) and assume they cannot be refreshed.
|
33
|
+
console.warn(
|
34
|
+
"[React Refresh] Failed to get exports for module: " + moduleId + "."
|
35
|
+
);
|
36
|
+
return {};
|
37
|
+
}
|
38
|
+
|
39
|
+
var exportsOrPromise = maybeModule.exports;
|
40
|
+
if (typeof Promise !== "undefined" && exportsOrPromise instanceof Promise) {
|
41
|
+
return exportsOrPromise.then(function (exports) {
|
42
|
+
return exports;
|
43
|
+
});
|
44
|
+
}
|
45
|
+
return exportsOrPromise;
|
46
|
+
}
|
47
|
+
|
48
|
+
/**
|
49
|
+
* Calculates the signature of a React refresh boundary.
|
50
|
+
* If this signature changes, it's unsafe to accept the boundary.
|
51
|
+
*
|
52
|
+
* This implementation is based on the one in [Metro](https://github.com/facebook/metro/blob/907d6af22ac6ebe58572be418e9253a90665ecbd/packages/metro/src/lib/polyfills/require.js#L795-L816).
|
53
|
+
* @param {*} moduleExports A Webpack module exports object.
|
54
|
+
* @returns {string[]} A React refresh boundary signature array.
|
55
|
+
*/
|
56
|
+
function getReactRefreshBoundarySignature(moduleExports) {
|
57
|
+
var signature = [];
|
58
|
+
signature.push(Refresh.getFamilyByType(moduleExports));
|
59
|
+
|
60
|
+
if (moduleExports == null || typeof moduleExports !== "object") {
|
61
|
+
// Exit if we can't iterate over exports.
|
62
|
+
return signature;
|
63
|
+
}
|
64
|
+
|
65
|
+
for (var key in moduleExports) {
|
66
|
+
if (key === "__esModule") {
|
67
|
+
continue;
|
68
|
+
}
|
69
|
+
|
70
|
+
signature.push(key);
|
71
|
+
signature.push(Refresh.getFamilyByType(moduleExports[key]));
|
72
|
+
}
|
73
|
+
|
74
|
+
return signature;
|
75
|
+
}
|
76
|
+
|
77
|
+
/**
|
78
|
+
* Creates a helper that performs a delayed React refresh.
|
79
|
+
* @returns {function(function(): void): void} A debounced React refresh function.
|
80
|
+
*/
|
81
|
+
function createDebounceUpdate() {
|
82
|
+
/**
|
83
|
+
* A cached setTimeout handler.
|
84
|
+
* @type {number | undefined}
|
85
|
+
*/
|
86
|
+
var refreshTimeout;
|
87
|
+
|
88
|
+
/**
|
89
|
+
* Performs react refresh on a delay and clears the error overlay.
|
90
|
+
* @param {function(): void} callback
|
91
|
+
* @returns {void}
|
92
|
+
*/
|
93
|
+
function enqueueUpdate(callback) {
|
94
|
+
if (typeof refreshTimeout === "undefined") {
|
95
|
+
refreshTimeout = setTimeout(function () {
|
96
|
+
refreshTimeout = undefined;
|
97
|
+
Refresh.performReactRefresh();
|
98
|
+
callback();
|
99
|
+
}, 30);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
return enqueueUpdate;
|
104
|
+
}
|
105
|
+
|
106
|
+
/**
|
107
|
+
* Checks if all exports are likely a React component.
|
108
|
+
*
|
109
|
+
* This implementation is based on the one in [Metro](https://github.com/facebook/metro/blob/febdba2383113c88296c61e28e4ef6a7f4939fda/packages/metro/src/lib/polyfills/require.js#L748-L774).
|
110
|
+
* @param {*} moduleExports A Webpack module exports object.
|
111
|
+
* @returns {boolean} Whether the exports are React component like.
|
112
|
+
*/
|
113
|
+
function isReactRefreshBoundary(moduleExports) {
|
114
|
+
if (Refresh.isLikelyComponentType(moduleExports)) {
|
115
|
+
return true;
|
116
|
+
}
|
117
|
+
if (
|
118
|
+
moduleExports === undefined ||
|
119
|
+
moduleExports === null ||
|
120
|
+
typeof moduleExports !== "object"
|
121
|
+
) {
|
122
|
+
// Exit if we can't iterate over exports.
|
123
|
+
return false;
|
124
|
+
}
|
125
|
+
|
126
|
+
var hasExports = false;
|
127
|
+
var areAllExportsComponents = true;
|
128
|
+
for (var key in moduleExports) {
|
129
|
+
hasExports = true;
|
130
|
+
|
131
|
+
// This is the ES Module indicator flag
|
132
|
+
if (key === "__esModule") {
|
133
|
+
continue;
|
134
|
+
}
|
135
|
+
|
136
|
+
// We can (and have to) safely execute getters here,
|
137
|
+
// as Webpack manually assigns harmony exports to getters,
|
138
|
+
// without any side-effects attached.
|
139
|
+
// Ref: https://github.com/webpack/webpack/blob/b93048643fe74de2a6931755911da1212df55897/lib/MainTemplate.js#L281
|
140
|
+
var exportValue = moduleExports[key];
|
141
|
+
if (!Refresh.isLikelyComponentType(exportValue)) {
|
142
|
+
areAllExportsComponents = false;
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
return hasExports && areAllExportsComponents;
|
147
|
+
}
|
148
|
+
|
149
|
+
/**
|
150
|
+
* Checks if exports are likely a React component and registers them.
|
151
|
+
*
|
152
|
+
* This implementation is based on the one in [Metro](https://github.com/facebook/metro/blob/febdba2383113c88296c61e28e4ef6a7f4939fda/packages/metro/src/lib/polyfills/require.js#L818-L835).
|
153
|
+
* @param {*} moduleExports A Webpack module exports object.
|
154
|
+
* @param {string} moduleId A Webpack module ID.
|
155
|
+
* @returns {void}
|
156
|
+
*/
|
157
|
+
function registerExportsForReactRefresh(moduleExports, moduleId) {
|
158
|
+
if (Refresh.isLikelyComponentType(moduleExports)) {
|
159
|
+
// Register module.exports if it is likely a component
|
160
|
+
Refresh.register(moduleExports, moduleId + " %exports%");
|
161
|
+
}
|
162
|
+
|
163
|
+
if (
|
164
|
+
moduleExports === undefined ||
|
165
|
+
moduleExports === null ||
|
166
|
+
typeof moduleExports !== "object"
|
167
|
+
) {
|
168
|
+
// Exit if we can't iterate over the exports.
|
169
|
+
return;
|
170
|
+
}
|
171
|
+
|
172
|
+
for (var key in moduleExports) {
|
173
|
+
// Skip registering the ES Module indicator
|
174
|
+
if (key === "__esModule") {
|
175
|
+
continue;
|
176
|
+
}
|
177
|
+
|
178
|
+
var exportValue = moduleExports[key];
|
179
|
+
if (Refresh.isLikelyComponentType(exportValue)) {
|
180
|
+
var typeID = moduleId + " %exports% " + key;
|
181
|
+
Refresh.register(exportValue, typeID);
|
182
|
+
}
|
183
|
+
}
|
184
|
+
}
|
185
|
+
|
186
|
+
/**
|
187
|
+
* Compares previous and next module objects to check for mutated boundaries.
|
188
|
+
*
|
189
|
+
* This implementation is based on the one in [Metro](https://github.com/facebook/metro/blob/907d6af22ac6ebe58572be418e9253a90665ecbd/packages/metro/src/lib/polyfills/require.js#L776-L792).
|
190
|
+
* @param {*} prevExports The current Webpack module exports object.
|
191
|
+
* @param {*} nextExports The next Webpack module exports object.
|
192
|
+
* @returns {boolean} Whether the React refresh boundary should be invalidated.
|
193
|
+
*/
|
194
|
+
function shouldInvalidateReactRefreshBoundary(prevExports, nextExports) {
|
195
|
+
var prevSignature = getReactRefreshBoundarySignature(prevExports);
|
196
|
+
var nextSignature = getReactRefreshBoundarySignature(nextExports);
|
197
|
+
|
198
|
+
if (prevSignature.length !== nextSignature.length) {
|
199
|
+
return true;
|
200
|
+
}
|
201
|
+
|
202
|
+
for (var i = 0; i < nextSignature.length; i += 1) {
|
203
|
+
if (prevSignature[i] !== nextSignature[i]) {
|
204
|
+
return true;
|
205
|
+
}
|
206
|
+
}
|
207
|
+
|
208
|
+
return false;
|
209
|
+
}
|
210
|
+
|
211
|
+
var enqueueUpdate = createDebounceUpdate();
|
212
|
+
function executeRuntime(
|
213
|
+
moduleExports,
|
214
|
+
moduleId,
|
215
|
+
webpackHot,
|
216
|
+
refreshOverlay,
|
217
|
+
isTest
|
218
|
+
) {
|
219
|
+
registerExportsForReactRefresh(moduleExports, moduleId);
|
220
|
+
|
221
|
+
if (webpackHot) {
|
222
|
+
var isHotUpdate = !!webpackHot.data;
|
223
|
+
var prevExports;
|
224
|
+
if (isHotUpdate) {
|
225
|
+
prevExports = webpackHot.data.prevExports;
|
226
|
+
}
|
227
|
+
|
228
|
+
if (isReactRefreshBoundary(moduleExports)) {
|
229
|
+
webpackHot.dispose(
|
230
|
+
/**
|
231
|
+
* A callback to performs a full refresh if React has unrecoverable errors,
|
232
|
+
* and also caches the to-be-disposed module.
|
233
|
+
* @param {*} data A hot module data object from Webpack HMR.
|
234
|
+
* @returns {void}
|
235
|
+
*/
|
236
|
+
function hotDisposeCallback(data) {
|
237
|
+
// We have to mutate the data object to get data registered and cached
|
238
|
+
data.prevExports = moduleExports;
|
239
|
+
}
|
240
|
+
);
|
241
|
+
webpackHot.accept(
|
242
|
+
/**
|
243
|
+
* An error handler to allow self-recovering behaviours.
|
244
|
+
* @param {Error} error An error occurred during evaluation of a module.
|
245
|
+
* @returns {void}
|
246
|
+
*/
|
247
|
+
function hotErrorHandler(error) {
|
248
|
+
if (typeof refreshOverlay !== "undefined" && refreshOverlay) {
|
249
|
+
refreshOverlay.handleRuntimeError(error);
|
250
|
+
}
|
251
|
+
|
252
|
+
if (typeof isTest !== "undefined" && isTest) {
|
253
|
+
if (window.onHotAcceptError) {
|
254
|
+
window.onHotAcceptError(error.message);
|
255
|
+
}
|
256
|
+
}
|
257
|
+
|
258
|
+
__webpack_require__.c[moduleId].hot.accept(hotErrorHandler);
|
259
|
+
}
|
260
|
+
);
|
261
|
+
|
262
|
+
if (isHotUpdate) {
|
263
|
+
if (
|
264
|
+
isReactRefreshBoundary(prevExports) &&
|
265
|
+
shouldInvalidateReactRefreshBoundary(prevExports, moduleExports)
|
266
|
+
) {
|
267
|
+
webpackHot.invalidate();
|
268
|
+
} else {
|
269
|
+
enqueueUpdate(
|
270
|
+
/**
|
271
|
+
* A function to dismiss the error overlay after performing React refresh.
|
272
|
+
* @returns {void}
|
273
|
+
*/
|
274
|
+
function updateCallback() {
|
275
|
+
if (typeof refreshOverlay !== "undefined" && refreshOverlay) {
|
276
|
+
refreshOverlay.clearRuntimeErrors();
|
277
|
+
}
|
278
|
+
}
|
279
|
+
);
|
280
|
+
}
|
281
|
+
}
|
282
|
+
} else {
|
283
|
+
if (isHotUpdate && typeof prevExports !== "undefined") {
|
284
|
+
webpackHot.invalidate();
|
285
|
+
}
|
286
|
+
}
|
287
|
+
}
|
288
|
+
}
|
289
|
+
|
290
|
+
module.exports = Object.freeze({
|
291
|
+
enqueueUpdate: enqueueUpdate,
|
292
|
+
executeRuntime: executeRuntime,
|
293
|
+
getModuleExports: getModuleExports,
|
294
|
+
isReactRefreshBoundary: isReactRefreshBoundary,
|
295
|
+
shouldInvalidateReactRefreshBoundary: shouldInvalidateReactRefreshBoundary,
|
296
|
+
registerExportsForReactRefresh: registerExportsForReactRefresh
|
297
|
+
});
|
package/dist/index.js
CHANGED
@@ -6,9 +6,7 @@ const path_1 = __importDefault(require("path"));
|
|
6
6
|
const options_1 = require("./options");
|
7
7
|
const reactRefreshPath = require.resolve("../client/reactRefresh.js");
|
8
8
|
const reactRefreshEntryPath = require.resolve("../client/reactRefreshEntry.js");
|
9
|
-
const refreshUtilsPath = require.resolve("
|
10
|
-
paths: [reactRefreshPath]
|
11
|
-
});
|
9
|
+
const refreshUtilsPath = require.resolve("../client/refreshUtils.js");
|
12
10
|
const refreshRuntimeDirPath = path_1.default.dirname(require.resolve("react-refresh", {
|
13
11
|
paths: [reactRefreshPath]
|
14
12
|
}));
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@rspack/plugin-react-refresh",
|
3
|
-
"version": "0.4.
|
3
|
+
"version": "0.4.2",
|
4
4
|
"license": "MIT",
|
5
5
|
"description": "React refresh plugin for rspack",
|
6
6
|
"main": "dist/index.js",
|
@@ -27,13 +27,10 @@
|
|
27
27
|
"url": "https://github.com/web-infra-dev/rspack",
|
28
28
|
"directory": "packages/rspack-plugin-react-refresh"
|
29
29
|
},
|
30
|
-
"dependencies": {
|
31
|
-
"@pmmmwh/react-refresh-webpack-plugin": "0.5.10"
|
32
|
-
},
|
33
30
|
"devDependencies": {
|
34
31
|
"react-refresh": "0.14.0",
|
35
|
-
"@rspack/core": "0.4.
|
36
|
-
"@rspack/plugin-react-refresh": "0.4.
|
32
|
+
"@rspack/core": "0.4.2",
|
33
|
+
"@rspack/plugin-react-refresh": "0.4.2"
|
37
34
|
},
|
38
35
|
"peerDependencies": {
|
39
36
|
"react-refresh": ">=0.10.0 <1.0.0"
|