@rspack/plugin-react-refresh 1.4.3 → 1.5.1
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 +35 -2
- package/client/overlay/index.js +6 -1
- package/client/reactRefresh.js +15 -1
- package/client/refreshUtils.js +14 -0
- package/dist/index.js +7 -0
- package/dist/options.d.ts +17 -3
- package/dist/options.js +1 -0
- package/exports/index.d.mts +1 -1
- package/package.json +15 -14
package/README.md
CHANGED
|
@@ -36,7 +36,6 @@ Import the plugin in your code:
|
|
|
36
36
|
```js
|
|
37
37
|
// Named import (recommended)
|
|
38
38
|
import { ReactRefreshRspackPlugin } from "@rspack/plugin-react-refresh";
|
|
39
|
-
|
|
40
39
|
```
|
|
41
40
|
|
|
42
41
|
- CommonJS:
|
|
@@ -101,12 +100,31 @@ Compared to the previous approach, this method decouples the React Fast Refresh
|
|
|
101
100
|
|
|
102
101
|
## Options
|
|
103
102
|
|
|
103
|
+
### test
|
|
104
|
+
|
|
105
|
+
- Type: [Rspack.RuleSetCondition](https://rspack.dev/config/module#condition)
|
|
106
|
+
- Default: `undefined`
|
|
107
|
+
|
|
108
|
+
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.
|
|
109
|
+
|
|
110
|
+
Works identically to Rspack's [rule.test](https://rspack.dev/config/module#ruletest) option.
|
|
111
|
+
|
|
112
|
+
```js
|
|
113
|
+
new ReactRefreshPlugin({
|
|
114
|
+
test: [/\.jsx$/, /\.tsx$/],
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
104
118
|
### include
|
|
105
119
|
|
|
106
120
|
- Type: [Rspack.RuleSetCondition](https://rspack.dev/config/module#condition)
|
|
107
121
|
- Default: `/\.([cm]js|[jt]sx?|flow)$/i`
|
|
108
122
|
|
|
109
|
-
|
|
123
|
+
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.
|
|
124
|
+
|
|
125
|
+
Use this to limit processing to specific directories or file patterns.
|
|
126
|
+
|
|
127
|
+
Works identically to Rspack's [rule.include](https://rspack.dev/config/module#ruleinclude) option.
|
|
110
128
|
|
|
111
129
|
```js
|
|
112
130
|
new ReactRefreshPlugin({
|
|
@@ -199,6 +217,21 @@ new ReactRefreshPlugin({
|
|
|
199
217
|
});
|
|
200
218
|
```
|
|
201
219
|
|
|
220
|
+
### reloadOnRuntimeErrors
|
|
221
|
+
|
|
222
|
+
- Type: `boolean`
|
|
223
|
+
- Default: `false`
|
|
224
|
+
|
|
225
|
+
Config the plugin whether trigger a full page reload when an unrecoverable runtime error is encountered.
|
|
226
|
+
|
|
227
|
+
Currently, only module factory undefined error is considered as unrecoverable runtime error.
|
|
228
|
+
|
|
229
|
+
```js
|
|
230
|
+
new ReactRefreshPlugin({
|
|
231
|
+
reloadOnRuntimeErrors: true,
|
|
232
|
+
});
|
|
233
|
+
```
|
|
234
|
+
|
|
202
235
|
## Credits
|
|
203
236
|
|
|
204
237
|
Thanks to the [react-refresh-webpack-plugin](https://github.com/pmmmwh/react-refresh-webpack-plugin) created by [@pmmmwh](https://github.com/pmmmwh), which inspires implement this plugin.
|
package/client/overlay/index.js
CHANGED
|
@@ -240,7 +240,12 @@ function render() {
|
|
|
240
240
|
*/
|
|
241
241
|
function cleanup() {
|
|
242
242
|
// Clean up and reset all internal state.
|
|
243
|
-
|
|
243
|
+
try {
|
|
244
|
+
document.body.removeChild(iframeRoot);
|
|
245
|
+
} catch (e) {
|
|
246
|
+
// In case user render react app directly to body, will trigger `NotFoundError` when recovery from an Error
|
|
247
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild#exceptions
|
|
248
|
+
}
|
|
244
249
|
scheduledRenderFn = null;
|
|
245
250
|
root = null;
|
|
246
251
|
iframeRoot = null;
|
package/client/reactRefresh.js
CHANGED
|
@@ -6,7 +6,21 @@ const RefreshRuntime = require('react-refresh/runtime');
|
|
|
6
6
|
function refresh(moduleId, webpackHot) {
|
|
7
7
|
const currentExports = RefreshUtils.getModuleExports(moduleId);
|
|
8
8
|
const fn = (exports) => {
|
|
9
|
-
|
|
9
|
+
var errorOverlay;
|
|
10
|
+
if (typeof __react_refresh_error_overlay__ !== 'undefined') {
|
|
11
|
+
errorOverlay = __react_refresh_error_overlay__;
|
|
12
|
+
}
|
|
13
|
+
var testMode;
|
|
14
|
+
if (typeof __react_refresh_test__ !== 'undefined') {
|
|
15
|
+
testMode = __react_refresh_test__;
|
|
16
|
+
}
|
|
17
|
+
RefreshUtils.executeRuntime(
|
|
18
|
+
exports,
|
|
19
|
+
moduleId,
|
|
20
|
+
webpackHot,
|
|
21
|
+
errorOverlay,
|
|
22
|
+
testMode,
|
|
23
|
+
);
|
|
10
24
|
};
|
|
11
25
|
if (typeof Promise !== 'undefined' && currentExports instanceof Promise) {
|
|
12
26
|
currentExports.then(fn);
|
package/client/refreshUtils.js
CHANGED
|
@@ -209,6 +209,7 @@ function shouldInvalidateReactRefreshBoundary(prevExports, nextExports) {
|
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
var enqueueUpdate = createDebounceUpdate();
|
|
212
|
+
|
|
212
213
|
function executeRuntime(
|
|
213
214
|
moduleExports,
|
|
214
215
|
moduleId,
|
|
@@ -245,6 +246,15 @@ function executeRuntime(
|
|
|
245
246
|
* @returns {void}
|
|
246
247
|
*/
|
|
247
248
|
function hotErrorHandler(error) {
|
|
249
|
+
console.error(error);
|
|
250
|
+
if (
|
|
251
|
+
__reload_on_runtime_errors__ &&
|
|
252
|
+
isUnrecoverableRuntimeError(error)
|
|
253
|
+
) {
|
|
254
|
+
location.reload();
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
|
|
248
258
|
if (typeof refreshOverlay !== 'undefined' && refreshOverlay) {
|
|
249
259
|
refreshOverlay.handleRuntimeError(error);
|
|
250
260
|
}
|
|
@@ -287,6 +297,10 @@ function executeRuntime(
|
|
|
287
297
|
}
|
|
288
298
|
}
|
|
289
299
|
|
|
300
|
+
function isUnrecoverableRuntimeError(error) {
|
|
301
|
+
return error.message.startsWith('RuntimeError: factory is undefined');
|
|
302
|
+
}
|
|
303
|
+
|
|
290
304
|
module.exports = Object.freeze({
|
|
291
305
|
enqueueUpdate: enqueueUpdate,
|
|
292
306
|
executeRuntime: executeRuntime,
|
package/dist/index.js
CHANGED
|
@@ -58,6 +58,7 @@ class ReactRefreshRspackPlugin {
|
|
|
58
58
|
}).apply(compiler);
|
|
59
59
|
if (this.options.injectLoader) {
|
|
60
60
|
compiler.options.module.rules.unshift({
|
|
61
|
+
test: this.options.test,
|
|
61
62
|
// biome-ignore lint: exists
|
|
62
63
|
include: this.options.include,
|
|
63
64
|
exclude: {
|
|
@@ -65,6 +66,11 @@ class ReactRefreshRspackPlugin {
|
|
|
65
66
|
or: [this.options.exclude, [...paths_1.runtimePaths]].filter(Boolean),
|
|
66
67
|
},
|
|
67
68
|
resourceQuery: this.options.resourceQuery,
|
|
69
|
+
dependency: {
|
|
70
|
+
// `new URL("static/sdk.js", import.meta.url)` the sdk.js is an asset module
|
|
71
|
+
// we shoudn't inject react refresh for asset module
|
|
72
|
+
not: ['url'],
|
|
73
|
+
},
|
|
68
74
|
use: ReactRefreshRspackPlugin.loader,
|
|
69
75
|
});
|
|
70
76
|
}
|
|
@@ -73,6 +79,7 @@ class ReactRefreshRspackPlugin {
|
|
|
73
79
|
__react_refresh_library__: JSON.stringify(compiler.webpack.Template.toIdentifier(this.options.library ||
|
|
74
80
|
compiler.options.output.uniqueName ||
|
|
75
81
|
compiler.options.output.library)),
|
|
82
|
+
__reload_on_runtime_errors__: this.options.reloadOnRuntimeErrors,
|
|
76
83
|
};
|
|
77
84
|
const providedModules = {
|
|
78
85
|
__react_refresh_utils__: paths_1.refreshUtilsPath,
|
package/dist/options.d.ts
CHANGED
|
@@ -11,11 +11,20 @@ interface OverlayOptions {
|
|
|
11
11
|
}
|
|
12
12
|
export type PluginOptions = {
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
14
|
+
* Specifies which files should be processed by the React Refresh loader.
|
|
15
|
+
* This option is passed to the `builtin:react-refresh-loader` as the `rule.test` condition.
|
|
16
|
+
* Works identically to Rspack's `rule.test` option.
|
|
17
17
|
* @see https://rspack.dev/config/module#ruletest
|
|
18
18
|
*/
|
|
19
|
+
test?: RuleSetCondition;
|
|
20
|
+
/**
|
|
21
|
+
* Explicitly includes files to be processed by the React Refresh loader.
|
|
22
|
+
* This option is passed to the `builtin:react-refresh-loader` as the `rule.include` condition.
|
|
23
|
+
* Use this to limit processing to specific directories or file patterns.
|
|
24
|
+
* Works identically to Rspack's `rule.include` option.
|
|
25
|
+
* @default /\.([cm]js|[jt]sx?|flow)$/i
|
|
26
|
+
* @see https://rspack.dev/config/module#ruleinclude
|
|
27
|
+
*/
|
|
19
28
|
include?: RuleSetCondition | null;
|
|
20
29
|
/**
|
|
21
30
|
* Exclude files from being processed by the plugin.
|
|
@@ -66,6 +75,11 @@ export type PluginOptions = {
|
|
|
66
75
|
* @default true
|
|
67
76
|
*/
|
|
68
77
|
injectEntry?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Whether to reload the page on runtime errors. E.g: undefined module factory
|
|
80
|
+
* @default false
|
|
81
|
+
*/
|
|
82
|
+
reloadOnRuntimeErrors?: boolean;
|
|
69
83
|
};
|
|
70
84
|
export interface NormalizedPluginOptions extends Required<PluginOptions> {
|
|
71
85
|
overlay: false | OverlayOptions;
|
package/dist/options.js
CHANGED
|
@@ -34,6 +34,7 @@ function normalizeOptions(options) {
|
|
|
34
34
|
d(options, 'forceEnable', false);
|
|
35
35
|
d(options, 'injectLoader', true);
|
|
36
36
|
d(options, 'injectEntry', true);
|
|
37
|
+
d(options, 'reloadOnRuntimeErrors', false);
|
|
37
38
|
options.overlay = normalizeOverlay(options.overlay);
|
|
38
39
|
return options;
|
|
39
40
|
}
|
package/exports/index.d.mts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rspack/plugin-react-refresh",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"repository": "https://github.com/rspack-contrib/rspack-plugin-react-refresh",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "React refresh plugin for Rspack",
|
|
@@ -32,24 +32,25 @@
|
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@biomejs/biome": "^1.9.4",
|
|
35
|
-
"@
|
|
36
|
-
"@
|
|
37
|
-
"@rspack/core": "1.3.8",
|
|
35
|
+
"@rslib/core": "^0.11.0",
|
|
36
|
+
"@rspack/core": "1.4.11",
|
|
38
37
|
"@types/jest": "29.5.14",
|
|
39
|
-
"@types/node": "^22.
|
|
40
|
-
"
|
|
41
|
-
"
|
|
38
|
+
"@types/node": "^22.17.0",
|
|
39
|
+
"bumpp": "^10.2.3",
|
|
40
|
+
"cac": "^6.7.14",
|
|
41
|
+
"cross-env": "^10.0.0",
|
|
42
|
+
"execa": "9.6.0",
|
|
42
43
|
"fs-extra": "11.3.0",
|
|
43
44
|
"jest": "29.7.0",
|
|
44
45
|
"jest-cli": "29.7.0",
|
|
45
46
|
"jest-environment-node": "29.7.0",
|
|
46
47
|
"nano-staged": "^0.8.0",
|
|
47
48
|
"react-refresh": "^0.17.0",
|
|
48
|
-
"semver": "7.7.
|
|
49
|
-
"simple-git-hooks": "^2.13.
|
|
50
|
-
"ts-jest": "29.
|
|
49
|
+
"semver": "7.7.2",
|
|
50
|
+
"simple-git-hooks": "^2.13.1",
|
|
51
|
+
"ts-jest": "29.4.0",
|
|
51
52
|
"ts-node": "^10.9.2",
|
|
52
|
-
"typescript": "5.
|
|
53
|
+
"typescript": "5.9.2"
|
|
53
54
|
},
|
|
54
55
|
"dependencies": {
|
|
55
56
|
"error-stack-parser": "^2.1.4",
|
|
@@ -66,8 +67,7 @@
|
|
|
66
67
|
},
|
|
67
68
|
"publishConfig": {
|
|
68
69
|
"access": "public",
|
|
69
|
-
"registry": "https://registry.npmjs.org/"
|
|
70
|
-
"provenance": true
|
|
70
|
+
"registry": "https://registry.npmjs.org/"
|
|
71
71
|
},
|
|
72
72
|
"scripts": {
|
|
73
73
|
"build": "tsc -b ./tsconfig.build.json",
|
|
@@ -75,6 +75,7 @@
|
|
|
75
75
|
"lint": "biome check .",
|
|
76
76
|
"lint:write": "biome check . --write",
|
|
77
77
|
"test": "jest --colors",
|
|
78
|
-
"release": "node ./scripts/release.mjs"
|
|
78
|
+
"release": "node ./scripts/release.mjs",
|
|
79
|
+
"bump": "npx bumpp --no-push --no-tag --no-commit"
|
|
79
80
|
}
|
|
80
81
|
}
|