@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 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
- Include files to be processed by the plugin. The value is the same as the [rule.test](https://rspack.dev/config/module#ruletest) option in Rspack.
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.
@@ -240,7 +240,12 @@ function render() {
240
240
  */
241
241
  function cleanup() {
242
242
  // Clean up and reset all internal state.
243
- document.body.removeChild(iframeRoot);
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;
@@ -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
- RefreshUtils.executeRuntime(exports, moduleId, webpackHot);
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);
@@ -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
- * Include files to be processed by the plugin.
15
- * The value is the same as the `rule.test` option in Rspack.
16
- * @default /\.([cm]js|[jt]sx?|flow)$/i
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
  }
@@ -1,4 +1,4 @@
1
- import { ReactRefreshRspackPlugin, type PluginOptions } from '../dist/index.js';
1
+ import { type PluginOptions, ReactRefreshRspackPlugin } from '../dist/index.js';
2
2
 
3
3
  export type { PluginOptions };
4
4
  export { ReactRefreshRspackPlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rspack/plugin-react-refresh",
3
- "version": "1.4.3",
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
- "@continuous-auth/client": "2.3.2",
36
- "@rslib/core": "^0.6.8",
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.15.3",
40
- "cross-env": "^7.0.3",
41
- "execa": "9.5.2",
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.1",
49
- "simple-git-hooks": "^2.13.0",
50
- "ts-jest": "29.3.2",
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.8.3"
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
  }