@rspack/plugin-react-refresh 1.6.2 → 2.0.0-beta.0
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/README.md +19 -57
- package/client/reactRefresh.js +16 -28
- package/client/reactRefreshEntry.js +11 -12
- package/client/refreshUtils.js +116 -133
- package/dist/index.d.ts +1 -6
- package/dist/index.js +10 -176
- package/dist/options.d.ts +3 -20
- package/package.json +24 -40
- package/client/errorOverlayEntry.js +0 -101
- package/client/overlay/components/CompileErrorTrace.js +0 -68
- package/client/overlay/components/PageHeader.js +0 -60
- package/client/overlay/components/RuntimeErrorFooter.js +0 -93
- package/client/overlay/components/RuntimeErrorHeader.js +0 -38
- package/client/overlay/components/RuntimeErrorStack.js +0 -80
- package/client/overlay/components/Spacer.js +0 -19
- package/client/overlay/containers/CompileErrorContainer.js +0 -25
- package/client/overlay/containers/RuntimeErrorContainer.js +0 -29
- package/client/overlay/index.js +0 -351
- package/client/overlay/theme.js +0 -39
- package/client/overlay/utils.js +0 -74
- package/client/utils/ansi-html.js +0 -300
- package/client/utils/errorEventHandlers.js +0 -102
- package/client/utils/formatWebpackErrors.js +0 -106
- package/client/utils/retry.js +0 -23
- package/dist/sockets/WDSSocket.d.ts +0 -13
- package/dist/sockets/WDSSocket.js +0 -63
- package/dist/sockets/WHMEventSource.d.ts +0 -26
- package/dist/sockets/WHMEventSource.js +0 -52
- package/dist/sockets/utils/getCurrentScriptSource.d.ts +0 -1
- package/dist/sockets/utils/getCurrentScriptSource.js +0 -45
- package/dist/sockets/utils/getSocketUrlParts.d.ts +0 -9
- package/dist/sockets/utils/getSocketUrlParts.js +0 -87
- package/dist/sockets/utils/getUrlFromParts.d.ts +0 -9
- package/dist/sockets/utils/getUrlFromParts.js +0 -49
- package/dist/sockets/utils/getWDSMetadata.d.ts +0 -16
- package/dist/sockets/utils/getWDSMetadata.js +0 -45
- package/dist/utils/getAdditionalEntries.d.ts +0 -9
- package/dist/utils/getIntegrationEntry.d.ts +0 -7
- package/dist/utils/getSocketIntegration.d.ts +0 -2
- package/exports/index.cjs +0 -7
- package/exports/index.d.cts +0 -3
- package/exports/index.d.mts +0 -5
- package/exports/index.mjs +0 -11
package/README.md
CHANGED
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
React refresh plugin for [Rspack](https://github.com/web-infra-dev/rspack).
|
|
10
10
|
|
|
11
|
+
## Versions
|
|
12
|
+
|
|
13
|
+
- `2.x`: For Rspack v2.
|
|
14
|
+
- `1.x`: For Rspack v1, see [v1.x - README](https://github.com/rstackjs/rspack-dev-server/tree/v1.x#rspackdev-server) for usage guide.
|
|
15
|
+
|
|
11
16
|
## Installation
|
|
12
17
|
|
|
13
18
|
First you need to install this plugin and its dependencies:
|
|
@@ -26,17 +31,8 @@ bun add @rspack/plugin-react-refresh react-refresh -D
|
|
|
26
31
|
|
|
27
32
|
Import the plugin in your code:
|
|
28
33
|
|
|
29
|
-
- ES modules:
|
|
30
|
-
|
|
31
|
-
```js
|
|
32
|
-
// Named import (recommended)
|
|
33
|
-
import { ReactRefreshRspackPlugin } from "@rspack/plugin-react-refresh";
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
- CommonJS:
|
|
37
|
-
|
|
38
34
|
```js
|
|
39
|
-
|
|
35
|
+
import { ReactRefreshRspackPlugin } from '@rspack/plugin-react-refresh';
|
|
40
36
|
```
|
|
41
37
|
|
|
42
38
|
## Usage
|
|
@@ -47,27 +43,22 @@ Enabling [React Fast Refresh](https://reactnative.dev/docs/fast-refresh) functio
|
|
|
47
43
|
- Code transformation can be added through loaders, such as [jsc.transform.react.refresh](https://swc.rs/docs/configuration/compilation#jsctransformreactrefresh) for [swc-loader](https://swc.rs/docs/usage/swc-loader) or the [react-refresh/babel](https://github.com/facebook/react/tree/main/packages/react-refresh) for [babel-loader](https://github.com/babel/babel-loader).
|
|
48
44
|
|
|
49
45
|
```js
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
disableTransformByDefault: true,
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
// ...
|
|
60
|
-
mode: isDev ? "development" : "production",
|
|
46
|
+
import { ReactRefreshRspackPlugin } from '@rspack/plugin-react-refresh';
|
|
47
|
+
|
|
48
|
+
const isDev = process.env.NODE_ENV === 'development';
|
|
49
|
+
|
|
50
|
+
export default {
|
|
51
|
+
mode: isDev ? 'development' : 'production',
|
|
61
52
|
module: {
|
|
62
53
|
rules: [
|
|
63
54
|
{
|
|
64
55
|
test: /\.jsx$/,
|
|
65
56
|
use: {
|
|
66
|
-
loader:
|
|
57
|
+
loader: 'builtin:swc-loader',
|
|
67
58
|
options: {
|
|
68
59
|
jsc: {
|
|
69
60
|
parser: {
|
|
70
|
-
syntax:
|
|
61
|
+
syntax: 'ecmascript',
|
|
71
62
|
jsx: true,
|
|
72
63
|
},
|
|
73
64
|
transform: {
|
|
@@ -82,7 +73,7 @@ module.exports = {
|
|
|
82
73
|
},
|
|
83
74
|
],
|
|
84
75
|
},
|
|
85
|
-
plugins: [isDev && new
|
|
76
|
+
plugins: [isDev && new ReactRefreshRspackPlugin()],
|
|
86
77
|
};
|
|
87
78
|
```
|
|
88
79
|
|
|
@@ -98,7 +89,7 @@ Compared to the previous approach, this method decouples the React Fast Refresh
|
|
|
98
89
|
### test
|
|
99
90
|
|
|
100
91
|
- Type: [Rspack.RuleSetCondition](https://rspack.rs/config/module-rules#condition)
|
|
101
|
-
- Default:
|
|
92
|
+
- Default: `/\.(?:js|jsx|mjs|cjs|ts|tsx|mts|cts)$/`
|
|
102
93
|
|
|
103
94
|
Specifies which files should be processed by the React Refresh loader. This option is passed to the `builtin:react-refresh-loader` as the `rule.test` condition.
|
|
104
95
|
|
|
@@ -113,7 +104,7 @@ new ReactRefreshPlugin({
|
|
|
113
104
|
### include
|
|
114
105
|
|
|
115
106
|
- Type: [Rspack.RuleSetCondition](https://rspack.rs/config/module-rules#condition)
|
|
116
|
-
- Default:
|
|
107
|
+
- Default: `undefined`
|
|
117
108
|
|
|
118
109
|
Explicitly includes files to be processed by the React Refresh loader. This option is passed to the `builtin:react-refresh-loader` as the `rule.include` condition.
|
|
119
110
|
|
|
@@ -185,33 +176,6 @@ Sets a namespace for the React Refresh runtime.
|
|
|
185
176
|
|
|
186
177
|
It is most useful when multiple instances of React Refresh is running together simultaneously.
|
|
187
178
|
|
|
188
|
-
### overlay
|
|
189
|
-
|
|
190
|
-
- Type: `boolean | OverlayOptions`
|
|
191
|
-
- Default: `false`
|
|
192
|
-
|
|
193
|
-
Modify the behavior of the error overlay.
|
|
194
|
-
|
|
195
|
-
Checkout [OverlayOptions](https://github.com/rstackjs/rspack-plugin-react-refresh/blob/main/src/options.ts#L4) type signature for more details.
|
|
196
|
-
|
|
197
|
-
- Enable the error overlay:
|
|
198
|
-
|
|
199
|
-
```js
|
|
200
|
-
new ReactRefreshPlugin({
|
|
201
|
-
overlay: true,
|
|
202
|
-
});
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
- Configure the error overlay:
|
|
206
|
-
|
|
207
|
-
```js
|
|
208
|
-
new ReactRefreshPlugin({
|
|
209
|
-
overlay: {
|
|
210
|
-
// ...
|
|
211
|
-
},
|
|
212
|
-
});
|
|
213
|
-
```
|
|
214
|
-
|
|
215
179
|
### reloadOnRuntimeErrors
|
|
216
180
|
|
|
217
181
|
- Type: `boolean`
|
|
@@ -232,13 +196,11 @@ new ReactRefreshPlugin({
|
|
|
232
196
|
- Type: `string`
|
|
233
197
|
- Default: `builtin:react-refresh-loader`
|
|
234
198
|
|
|
235
|
-
|
|
236
|
-
the React Refresh utilities into each module. `reactRefreshLoader` option allows to specify the loader, that implements
|
|
237
|
-
custom React Refresh instrumentation if needed.
|
|
199
|
+
By default, the plugin uses the `builtin:react-refresh-loader` loader implementation [from Rspack](https://github.com/web-infra-dev/rspack/tree/main/crates/rspack_loader_react_refresh) to inject the React Refresh utilities into each module. The `reactRefreshLoader` option allows you to specify a loader that implements custom React Refresh instrumentation if needed.
|
|
238
200
|
|
|
239
201
|
```js
|
|
240
202
|
new ReactRefreshPlugin({
|
|
241
|
-
|
|
203
|
+
reactRefreshLoader: 'my-advanced-react-refresh-loader',
|
|
242
204
|
});
|
|
243
205
|
```
|
|
244
206
|
|
package/client/reactRefresh.js
CHANGED
|
@@ -1,35 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
createSignatureFunctionForTransform,
|
|
3
|
+
register,
|
|
4
|
+
} from 'react-refresh/runtime';
|
|
5
|
+
import { executeRuntime, getModuleExports } from './refreshUtils.js';
|
|
3
6
|
|
|
4
|
-
function refresh(moduleId,
|
|
5
|
-
const currentExports =
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (typeof __react_refresh_test__ !== 'undefined') {
|
|
13
|
-
testMode = __react_refresh_test__;
|
|
14
|
-
}
|
|
15
|
-
RefreshUtils.executeRuntime(
|
|
16
|
-
exports,
|
|
17
|
-
moduleId,
|
|
18
|
-
webpackHot,
|
|
19
|
-
errorOverlay,
|
|
20
|
-
testMode,
|
|
21
|
-
);
|
|
7
|
+
function refresh(moduleId, hot) {
|
|
8
|
+
const currentExports = getModuleExports(moduleId);
|
|
9
|
+
const runRefresh = (moduleExports) => {
|
|
10
|
+
const testMode =
|
|
11
|
+
typeof __react_refresh_test__ !== 'undefined'
|
|
12
|
+
? __react_refresh_test__
|
|
13
|
+
: undefined;
|
|
14
|
+
executeRuntime(moduleExports, moduleId, hot, testMode);
|
|
22
15
|
};
|
|
23
16
|
if (typeof Promise !== 'undefined' && currentExports instanceof Promise) {
|
|
24
|
-
currentExports.then(
|
|
17
|
+
currentExports.then(runRefresh);
|
|
25
18
|
} else {
|
|
26
|
-
|
|
19
|
+
runRefresh(currentExports);
|
|
27
20
|
}
|
|
28
21
|
}
|
|
29
22
|
|
|
30
|
-
|
|
31
|
-
refresh,
|
|
32
|
-
register: RefreshRuntime.register,
|
|
33
|
-
createSignatureFunctionForTransform:
|
|
34
|
-
RefreshRuntime.createSignatureFunctionForTransform,
|
|
35
|
-
};
|
|
23
|
+
export { createSignatureFunctionForTransform, refresh, register };
|
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { injectIntoGlobalHook } from 'react-refresh/runtime';
|
|
2
|
+
|
|
3
|
+
const safeThis = (() => {
|
|
3
4
|
// copied from core-js-pure/features/global-this
|
|
4
5
|
'use strict';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
return it && it.Math == Math && it;
|
|
8
|
-
};
|
|
7
|
+
const check = (it) => it && it.Math === Math && it;
|
|
9
8
|
|
|
10
9
|
// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
|
|
11
10
|
// eslint-disable-next-line es/no-global-this -- safe
|
|
12
11
|
return (
|
|
13
|
-
check(typeof globalThis
|
|
14
|
-
check(typeof window
|
|
12
|
+
check(typeof globalThis === 'object' && globalThis) ||
|
|
13
|
+
check(typeof window === 'object' && window) ||
|
|
15
14
|
// eslint-disable-next-line no-restricted-globals -- safe
|
|
16
|
-
check(typeof self
|
|
17
|
-
check(typeof __webpack_require__.g
|
|
15
|
+
check(typeof self === 'object' && self) ||
|
|
16
|
+
check(typeof __webpack_require__.g === 'object' && __webpack_require__.g) ||
|
|
18
17
|
// eslint-disable-next-line no-new-func -- fallback
|
|
19
18
|
(function () {
|
|
20
19
|
return this;
|
|
@@ -26,18 +25,18 @@ var safeThis = (function () {
|
|
|
26
25
|
|
|
27
26
|
if (process.env.NODE_ENV !== 'production') {
|
|
28
27
|
if (typeof safeThis !== 'undefined') {
|
|
29
|
-
|
|
28
|
+
let $RefreshInjected$ = '__reactRefreshInjected';
|
|
30
29
|
// Namespace the injected flag (if necessary) for monorepo compatibility
|
|
31
30
|
if (
|
|
32
31
|
typeof __react_refresh_library__ !== 'undefined' &&
|
|
33
32
|
__react_refresh_library__
|
|
34
33
|
) {
|
|
35
|
-
$RefreshInjected$ +=
|
|
34
|
+
$RefreshInjected$ += `_${__react_refresh_library__}`;
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
// Only inject the runtime if it hasn't been injected
|
|
39
38
|
if (!safeThis[$RefreshInjected$]) {
|
|
40
|
-
|
|
39
|
+
injectIntoGlobalHook(safeThis);
|
|
41
40
|
|
|
42
41
|
// Empty implementation to avoid "ReferenceError: variable is not defined" in module which didn't pass builtin:react-refresh-loader
|
|
43
42
|
safeThis.$RefreshSig$ = () => (type) => type;
|
package/client/refreshUtils.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
/* global __webpack_require__ */
|
|
2
|
-
|
|
2
|
+
import {
|
|
3
|
+
getFamilyByType,
|
|
4
|
+
isLikelyComponentType,
|
|
5
|
+
performReactRefresh,
|
|
6
|
+
register,
|
|
7
|
+
} from 'react-refresh/runtime';
|
|
3
8
|
|
|
4
9
|
/**
|
|
5
|
-
* Extracts exports from a
|
|
6
|
-
* @param {string} moduleId
|
|
10
|
+
* Extracts exports from a Rspack module object.
|
|
11
|
+
* @param {string} moduleId An Rspack module ID.
|
|
7
12
|
* @returns {*} An exports object from the module.
|
|
8
13
|
*/
|
|
9
14
|
function getModuleExports(moduleId) {
|
|
@@ -15,23 +20,22 @@ function getModuleExports(moduleId) {
|
|
|
15
20
|
return {};
|
|
16
21
|
}
|
|
17
22
|
|
|
18
|
-
|
|
23
|
+
const maybeModule = __webpack_require__.c[moduleId];
|
|
19
24
|
if (typeof maybeModule === 'undefined') {
|
|
20
25
|
// `moduleId` is available but the module in cache is unavailable,
|
|
21
|
-
// which indicates the module is somehow corrupted (e.g. broken
|
|
26
|
+
// which indicates the module is somehow corrupted (e.g. broken Rspack `module` globals).
|
|
22
27
|
// We will warn the user (as this is likely a mistake) and assume they cannot be refreshed.
|
|
23
28
|
console.warn(
|
|
24
|
-
|
|
29
|
+
`[React Refresh] Failed to get exports for module: ${moduleId}.`,
|
|
25
30
|
);
|
|
26
31
|
return {};
|
|
27
32
|
}
|
|
28
33
|
|
|
29
|
-
|
|
34
|
+
const exportsOrPromise = maybeModule.exports;
|
|
30
35
|
if (typeof Promise !== 'undefined' && exportsOrPromise instanceof Promise) {
|
|
31
|
-
return exportsOrPromise.then(
|
|
32
|
-
return exports;
|
|
33
|
-
});
|
|
36
|
+
return exportsOrPromise.then((moduleExports) => moduleExports);
|
|
34
37
|
}
|
|
38
|
+
|
|
35
39
|
return exportsOrPromise;
|
|
36
40
|
}
|
|
37
41
|
|
|
@@ -40,25 +44,24 @@ function getModuleExports(moduleId) {
|
|
|
40
44
|
* If this signature changes, it's unsafe to accept the boundary.
|
|
41
45
|
*
|
|
42
46
|
* 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).
|
|
43
|
-
* @param {*} moduleExports
|
|
47
|
+
* @param {*} moduleExports An Rspack module exports object.
|
|
44
48
|
* @returns {string[]} A React refresh boundary signature array.
|
|
45
49
|
*/
|
|
46
50
|
function getReactRefreshBoundarySignature(moduleExports) {
|
|
47
|
-
|
|
48
|
-
signature.push(Refresh.getFamilyByType(moduleExports));
|
|
51
|
+
const signature = [getFamilyByType(moduleExports)];
|
|
49
52
|
|
|
50
53
|
if (moduleExports == null || typeof moduleExports !== 'object') {
|
|
51
54
|
// Exit if we can't iterate over exports.
|
|
52
55
|
return signature;
|
|
53
56
|
}
|
|
54
57
|
|
|
55
|
-
for (
|
|
58
|
+
for (const key in moduleExports) {
|
|
56
59
|
if (key === '__esModule') {
|
|
57
60
|
continue;
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
signature.push(key);
|
|
61
|
-
signature.push(
|
|
64
|
+
signature.push(getFamilyByType(moduleExports[key]));
|
|
62
65
|
}
|
|
63
66
|
|
|
64
67
|
return signature;
|
|
@@ -73,22 +76,26 @@ function createDebounceUpdate() {
|
|
|
73
76
|
* A cached setTimeout handler.
|
|
74
77
|
* @type {number | undefined}
|
|
75
78
|
*/
|
|
76
|
-
|
|
79
|
+
let refreshTimeout;
|
|
77
80
|
|
|
78
81
|
/**
|
|
79
|
-
* Performs
|
|
80
|
-
* @param {function(): void} callback
|
|
82
|
+
* Performs React Refresh on a delay.
|
|
83
|
+
* @param {function(): void} [callback]
|
|
81
84
|
* @returns {void}
|
|
82
85
|
*/
|
|
83
|
-
|
|
84
|
-
if (typeof refreshTimeout
|
|
85
|
-
|
|
86
|
-
refreshTimeout = undefined;
|
|
87
|
-
Refresh.performReactRefresh();
|
|
88
|
-
callback();
|
|
89
|
-
}, 30);
|
|
86
|
+
const enqueueUpdate = (callback) => {
|
|
87
|
+
if (typeof refreshTimeout !== 'undefined') {
|
|
88
|
+
return;
|
|
90
89
|
}
|
|
91
|
-
|
|
90
|
+
|
|
91
|
+
refreshTimeout = setTimeout(() => {
|
|
92
|
+
refreshTimeout = undefined;
|
|
93
|
+
performReactRefresh();
|
|
94
|
+
if (callback) {
|
|
95
|
+
callback();
|
|
96
|
+
}
|
|
97
|
+
}, 30);
|
|
98
|
+
};
|
|
92
99
|
|
|
93
100
|
return enqueueUpdate;
|
|
94
101
|
}
|
|
@@ -97,11 +104,11 @@ function createDebounceUpdate() {
|
|
|
97
104
|
* Checks if all exports are likely a React component.
|
|
98
105
|
*
|
|
99
106
|
* 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).
|
|
100
|
-
* @param {*} moduleExports
|
|
107
|
+
* @param {*} moduleExports An Rspack module exports object.
|
|
101
108
|
* @returns {boolean} Whether the exports are React component like.
|
|
102
109
|
*/
|
|
103
110
|
function isReactRefreshBoundary(moduleExports) {
|
|
104
|
-
if (
|
|
111
|
+
if (isLikelyComponentType(moduleExports)) {
|
|
105
112
|
return true;
|
|
106
113
|
}
|
|
107
114
|
if (
|
|
@@ -113,9 +120,9 @@ function isReactRefreshBoundary(moduleExports) {
|
|
|
113
120
|
return false;
|
|
114
121
|
}
|
|
115
122
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
for (
|
|
123
|
+
let hasExports = false;
|
|
124
|
+
let areAllExportsComponents = true;
|
|
125
|
+
for (const key in moduleExports) {
|
|
119
126
|
hasExports = true;
|
|
120
127
|
|
|
121
128
|
// This is the ES Module indicator flag
|
|
@@ -124,11 +131,11 @@ function isReactRefreshBoundary(moduleExports) {
|
|
|
124
131
|
}
|
|
125
132
|
|
|
126
133
|
// We can (and have to) safely execute getters here,
|
|
127
|
-
// as
|
|
134
|
+
// as Rspack/webpack manually assigns ESM exports to getters,
|
|
128
135
|
// without any side-effects attached.
|
|
129
136
|
// Ref: https://github.com/webpack/webpack/blob/b93048643fe74de2a6931755911da1212df55897/lib/MainTemplate.js#L281
|
|
130
|
-
|
|
131
|
-
if (!
|
|
137
|
+
const exportValue = moduleExports[key];
|
|
138
|
+
if (!isLikelyComponentType(exportValue)) {
|
|
132
139
|
areAllExportsComponents = false;
|
|
133
140
|
}
|
|
134
141
|
}
|
|
@@ -140,14 +147,14 @@ function isReactRefreshBoundary(moduleExports) {
|
|
|
140
147
|
* Checks if exports are likely a React component and registers them.
|
|
141
148
|
*
|
|
142
149
|
* 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).
|
|
143
|
-
* @param {*} moduleExports
|
|
144
|
-
* @param {string} moduleId
|
|
150
|
+
* @param {*} moduleExports An Rspack module exports object.
|
|
151
|
+
* @param {string} moduleId An Rspack module ID.
|
|
145
152
|
* @returns {void}
|
|
146
153
|
*/
|
|
147
154
|
function registerExportsForReactRefresh(moduleExports, moduleId) {
|
|
148
|
-
if (
|
|
155
|
+
if (isLikelyComponentType(moduleExports)) {
|
|
149
156
|
// Register module.exports if it is likely a component
|
|
150
|
-
|
|
157
|
+
register(moduleExports, `${moduleId} %exports%`);
|
|
151
158
|
}
|
|
152
159
|
|
|
153
160
|
if (
|
|
@@ -159,16 +166,16 @@ function registerExportsForReactRefresh(moduleExports, moduleId) {
|
|
|
159
166
|
return;
|
|
160
167
|
}
|
|
161
168
|
|
|
162
|
-
for (
|
|
169
|
+
for (const key in moduleExports) {
|
|
163
170
|
// Skip registering the ES Module indicator
|
|
164
171
|
if (key === '__esModule') {
|
|
165
172
|
continue;
|
|
166
173
|
}
|
|
167
174
|
|
|
168
|
-
|
|
169
|
-
if (
|
|
170
|
-
|
|
171
|
-
|
|
175
|
+
const exportValue = moduleExports[key];
|
|
176
|
+
if (isLikelyComponentType(exportValue)) {
|
|
177
|
+
const typeID = `${moduleId} %exports% ${key}`;
|
|
178
|
+
register(exportValue, typeID);
|
|
172
179
|
}
|
|
173
180
|
}
|
|
174
181
|
}
|
|
@@ -177,111 +184,87 @@ function registerExportsForReactRefresh(moduleExports, moduleId) {
|
|
|
177
184
|
* Compares previous and next module objects to check for mutated boundaries.
|
|
178
185
|
*
|
|
179
186
|
* 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).
|
|
180
|
-
* @param {*} prevExports The current
|
|
181
|
-
* @param {*} nextExports The next
|
|
187
|
+
* @param {*} prevExports The current Rspack module exports object.
|
|
188
|
+
* @param {*} nextExports The next Rspack module exports object.
|
|
182
189
|
* @returns {boolean} Whether the React refresh boundary should be invalidated.
|
|
183
190
|
*/
|
|
184
191
|
function shouldInvalidateReactRefreshBoundary(prevExports, nextExports) {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
return true;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
return false;
|
|
192
|
+
const prevSignature = getReactRefreshBoundarySignature(prevExports);
|
|
193
|
+
const nextSignature = getReactRefreshBoundarySignature(nextExports);
|
|
194
|
+
|
|
195
|
+
return (
|
|
196
|
+
prevSignature.length !== nextSignature.length ||
|
|
197
|
+
nextSignature.some(
|
|
198
|
+
(signatureItem, index) => prevSignature[index] !== signatureItem,
|
|
199
|
+
)
|
|
200
|
+
);
|
|
199
201
|
}
|
|
200
202
|
|
|
201
|
-
|
|
203
|
+
const enqueueUpdate = createDebounceUpdate();
|
|
202
204
|
|
|
203
|
-
function executeRuntime(
|
|
204
|
-
moduleExports,
|
|
205
|
-
moduleId,
|
|
206
|
-
webpackHot,
|
|
207
|
-
refreshOverlay,
|
|
208
|
-
isTest,
|
|
209
|
-
) {
|
|
205
|
+
function executeRuntime(moduleExports, moduleId, hot, isTest) {
|
|
210
206
|
registerExportsForReactRefresh(moduleExports, moduleId);
|
|
211
207
|
|
|
212
|
-
if (
|
|
213
|
-
|
|
214
|
-
|
|
208
|
+
if (hot) {
|
|
209
|
+
const isHotUpdate = Boolean(hot.data);
|
|
210
|
+
let prevExports;
|
|
215
211
|
if (isHotUpdate) {
|
|
216
|
-
prevExports =
|
|
212
|
+
prevExports = hot.data.prevExports;
|
|
217
213
|
}
|
|
218
214
|
|
|
219
215
|
if (isReactRefreshBoundary(moduleExports)) {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
__webpack_require__.c[moduleId].hot.accept(hotErrorHandler);
|
|
259
|
-
},
|
|
260
|
-
);
|
|
216
|
+
/**
|
|
217
|
+
* A callback to perform a full refresh if React has unrecoverable errors,
|
|
218
|
+
* and also caches the to-be-disposed module.
|
|
219
|
+
* @param {*} data A hot module data object from Rspack HMR.
|
|
220
|
+
* @returns {void}
|
|
221
|
+
*/
|
|
222
|
+
const hotDisposeCallback = (data) => {
|
|
223
|
+
// We have to mutate the data object to get data registered and cached
|
|
224
|
+
data.prevExports = moduleExports;
|
|
225
|
+
};
|
|
226
|
+
/**
|
|
227
|
+
* An error handler to allow self-recovering behaviors.
|
|
228
|
+
* @param {Error} error An error occurred during evaluation of a module.
|
|
229
|
+
* @returns {void}
|
|
230
|
+
*/
|
|
231
|
+
const hotErrorHandler = (error) => {
|
|
232
|
+
console.error(error);
|
|
233
|
+
if (
|
|
234
|
+
__reload_on_runtime_errors__ &&
|
|
235
|
+
isUnrecoverableRuntimeError(error)
|
|
236
|
+
) {
|
|
237
|
+
location.reload();
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (
|
|
242
|
+
typeof isTest !== 'undefined' &&
|
|
243
|
+
isTest &&
|
|
244
|
+
window.onHotAcceptError
|
|
245
|
+
) {
|
|
246
|
+
window.onHotAcceptError(error.message);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
__webpack_require__.c[moduleId].hot.accept(hotErrorHandler);
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
hot.dispose(hotDisposeCallback);
|
|
253
|
+
hot.accept(hotErrorHandler);
|
|
261
254
|
|
|
262
255
|
if (isHotUpdate) {
|
|
263
256
|
if (
|
|
264
257
|
isReactRefreshBoundary(prevExports) &&
|
|
265
258
|
shouldInvalidateReactRefreshBoundary(prevExports, moduleExports)
|
|
266
259
|
) {
|
|
267
|
-
|
|
260
|
+
hot.invalidate();
|
|
268
261
|
} 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
|
-
);
|
|
262
|
+
enqueueUpdate();
|
|
280
263
|
}
|
|
281
264
|
}
|
|
282
265
|
} else {
|
|
283
266
|
if (isHotUpdate && typeof prevExports !== 'undefined') {
|
|
284
|
-
|
|
267
|
+
hot.invalidate();
|
|
285
268
|
}
|
|
286
269
|
}
|
|
287
270
|
}
|
|
@@ -291,11 +274,11 @@ function isUnrecoverableRuntimeError(error) {
|
|
|
291
274
|
return error.message.startsWith('RuntimeError: factory is undefined');
|
|
292
275
|
}
|
|
293
276
|
|
|
294
|
-
|
|
295
|
-
enqueueUpdate
|
|
296
|
-
executeRuntime
|
|
297
|
-
getModuleExports
|
|
298
|
-
isReactRefreshBoundary
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
}
|
|
277
|
+
export {
|
|
278
|
+
enqueueUpdate,
|
|
279
|
+
executeRuntime,
|
|
280
|
+
getModuleExports,
|
|
281
|
+
isReactRefreshBoundary,
|
|
282
|
+
registerExportsForReactRefresh,
|
|
283
|
+
shouldInvalidateReactRefreshBoundary,
|
|
284
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import type { Compiler } from '@rspack/core';
|
|
2
|
-
import type { NormalizedPluginOptions, PluginOptions } from './options';
|
|
2
|
+
import type { NormalizedPluginOptions, PluginOptions } from './options.js';
|
|
3
3
|
export type { PluginOptions };
|
|
4
4
|
declare class ReactRefreshRspackPlugin {
|
|
5
5
|
options: NormalizedPluginOptions;
|
|
6
|
-
/**
|
|
7
|
-
* @deprecated
|
|
8
|
-
*/
|
|
9
|
-
static get deprecated_runtimePaths(): string[];
|
|
10
6
|
constructor(options?: PluginOptions);
|
|
11
7
|
apply(compiler: Compiler): void;
|
|
12
8
|
}
|
|
13
9
|
export { ReactRefreshRspackPlugin };
|
|
14
|
-
export default ReactRefreshRspackPlugin;
|