@rspack/plugin-react-refresh 1.0.0-beta.3 → 1.0.0-beta.5
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/LICENSE +0 -1
- package/README.md +67 -3
- package/client/errorOverlayEntry.js +9 -7
- package/client/overlay/components/CompileErrorTrace.js +7 -2
- package/client/overlay/components/PageHeader.js +4 -2
- package/client/overlay/components/RuntimeErrorHeader.js +2 -1
- package/client/overlay/components/RuntimeErrorStack.js +2 -1
- package/client/overlay/index.js +10 -3
- package/client/overlay/utils.js +1 -1
- package/client/reactRefresh.js +15 -15
- package/client/reactRefreshEntry.js +41 -41
- package/client/refreshUtils.js +213 -213
- package/client/utils/ansi-html.js +80 -78
- package/client/utils/errorEventHandlers.js +2 -2
- package/client/utils/formatWebpackErrors.js +15 -5
- package/client/utils/retry.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +21 -19
- package/dist/options.d.ts +1 -1
- package/dist/options.js +10 -10
- package/dist/sockets/WDSSocket.d.ts +2 -2
- package/dist/sockets/WDSSocket.js +2 -2
- package/dist/sockets/utils/getCurrentScriptSource.js +4 -4
- package/dist/sockets/utils/getSocketUrlParts.d.ts +1 -1
- package/dist/sockets/utils/getSocketUrlParts.js +13 -12
- package/dist/sockets/utils/getUrlFromParts.d.ts +2 -2
- package/dist/sockets/utils/getUrlFromParts.js +3 -3
- package/dist/sockets/utils/getWDSMetadata.d.ts +3 -3
- package/dist/sockets/utils/getWDSMetadata.js +6 -6
- package/dist/utils/getAdditionalEntries.d.ts +2 -2
- package/dist/utils/getAdditionalEntries.js +11 -11
- package/dist/utils/getSocketIntegration.d.ts +1 -1
- package/dist/utils/getSocketIntegration.js +2 -2
- package/package.json +32 -21
package/LICENSE
CHANGED
@@ -2,7 +2,6 @@ MIT License
|
|
2
2
|
|
3
3
|
Copyright (c) 2022-present Bytedance, Inc. and its affiliates.
|
4
4
|
|
5
|
-
|
6
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
6
|
of this software and associated documentation files (the "Software"), to deal
|
8
7
|
in the Software without restriction, including without limitation the rights
|
package/README.md
CHANGED
@@ -5,11 +5,75 @@
|
|
5
5
|
|
6
6
|
# @rspack/plugin-react-refresh
|
7
7
|
|
8
|
-
React refresh plugin for rspack.
|
8
|
+
React refresh plugin for [Rspack](https://github.com/web-infra-dev/rspack).
|
9
9
|
|
10
|
-
##
|
10
|
+
## Installation
|
11
11
|
|
12
|
-
|
12
|
+
First you need to install this plugin and its dependencies:
|
13
|
+
|
14
|
+
```bash
|
15
|
+
npm add @rspack/plugin-react-refresh react-refresh -D
|
16
|
+
# or
|
17
|
+
yarn add @rspack/plugin-react-refresh react-refresh -D
|
18
|
+
# or
|
19
|
+
pnpm add @rspack/plugin-react-refresh react-refresh -D
|
20
|
+
# or
|
21
|
+
bun add @rspack/plugin-react-refresh react-refresh -D
|
22
|
+
```
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
Enabling [React Fast Refresh](https://reactnative.dev/docs/fast-refresh) functionality primarily involves two aspects: code injection and code transformation.
|
27
|
+
|
28
|
+
- Code injection will inject some code from the [react-refresh](https://www.npmjs.com/package/react-refresh) package, as well as some custom runtime code, all of which are integrated in this plugin and can be injected through.
|
29
|
+
- 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).
|
30
|
+
|
31
|
+
```js
|
32
|
+
const ReactRefreshPlugin = require('@rspack/plugin-react-refresh');
|
33
|
+
const isDev = process.env.NODE_ENV === 'development';
|
34
|
+
|
35
|
+
module.exports = {
|
36
|
+
experiments: {
|
37
|
+
rspackFuture: {
|
38
|
+
disableTransformByDefault: true,
|
39
|
+
},
|
40
|
+
},
|
41
|
+
// ...
|
42
|
+
mode: isDev ? 'development' : 'production',
|
43
|
+
module: {
|
44
|
+
rules: [
|
45
|
+
{
|
46
|
+
test: /\.jsx$/,
|
47
|
+
use: {
|
48
|
+
loader: 'builtin:swc-loader',
|
49
|
+
options: {
|
50
|
+
jsc: {
|
51
|
+
parser: {
|
52
|
+
syntax: 'ecmascript',
|
53
|
+
jsx: true,
|
54
|
+
},
|
55
|
+
transform: {
|
56
|
+
react: {
|
57
|
+
development: isDev,
|
58
|
+
refresh: isDev,
|
59
|
+
},
|
60
|
+
},
|
61
|
+
},
|
62
|
+
},
|
63
|
+
},
|
64
|
+
},
|
65
|
+
],
|
66
|
+
},
|
67
|
+
plugins: [isDev && new ReactRefreshPlugin()].filter(Boolean),
|
68
|
+
};
|
69
|
+
```
|
70
|
+
|
71
|
+
Compared to the previous approach, this method decouples the React Fast Refresh code injection logic from the transformation logic. The code injection logic is handled uniformly by this plugin, while the code transformation is handled by loaders. This means that this plugin can be used in conjunction with `builtin:swc-loader`, `swc-loader`, or `babel-loader`.
|
72
|
+
|
73
|
+
## Example
|
74
|
+
|
75
|
+
- For usage with `builtin:swc-loader`, you can refer to the example at [examples/react-refresh](https://github.com/rspack-contrib/rspack-examples/tree/main/rspack/react-refresh/rspack.config.js), When using with `swc-loader`, simply replace `builtin:swc-loader` with `swc-loader`.
|
76
|
+
- For usage with `babel-loader`, you can refer to the example at [examples/react-refresh-babel-loader](https://github.com/rspack-contrib/rspack-examples/tree/main/rspack/react-refresh-babel-loader/rspack.config.js)
|
13
77
|
|
14
78
|
## License
|
15
79
|
|
@@ -94,15 +94,17 @@ if (process.env.NODE_ENV !== 'production') {
|
|
94
94
|
hasRuntimeErrors = true;
|
95
95
|
__react_refresh_error_overlay__.handleRuntimeError(error);
|
96
96
|
});
|
97
|
-
events.handleUnhandledRejection(
|
98
|
-
|
99
|
-
|
100
|
-
|
97
|
+
events.handleUnhandledRejection(
|
98
|
+
function handleUnhandledPromiseRejection(error) {
|
99
|
+
hasRuntimeErrors = true;
|
100
|
+
__react_refresh_error_overlay__.handleRuntimeError(error);
|
101
|
+
},
|
102
|
+
);
|
101
103
|
|
102
104
|
// Mark overlay as injected to prevent double-injection
|
103
105
|
window.__reactRefreshOverlayInjected = true;
|
104
106
|
}
|
105
|
-
}
|
106
|
-
setupOverlay()
|
107
|
+
}
|
108
|
+
setupOverlay();
|
107
109
|
}
|
108
|
-
}
|
110
|
+
}
|
@@ -33,8 +33,13 @@ function CompileErrorTrace(document, root, props) {
|
|
33
33
|
|
34
34
|
const stackContainer = document.createElement('pre');
|
35
35
|
stackContainer.innerHTML = entities.decode(
|
36
|
-
ansiHTML(
|
37
|
-
|
36
|
+
ansiHTML(
|
37
|
+
entities.encode(errorParts.join('\n'), {
|
38
|
+
level: 'html5',
|
39
|
+
mode: 'nonAscii',
|
40
|
+
}),
|
41
|
+
),
|
42
|
+
{ level: 'html5' },
|
38
43
|
);
|
39
44
|
stackContainer.style.fontFamily = [
|
40
45
|
'"Operator Mono SSm"',
|
@@ -23,8 +23,10 @@ function PageHeader(document, root, props) {
|
|
23
23
|
pageHeaderContainer.style.left = '0';
|
24
24
|
pageHeaderContainer.style.right = '0';
|
25
25
|
pageHeaderContainer.style.padding = '1rem 1.5rem';
|
26
|
-
pageHeaderContainer.style.paddingLeft =
|
27
|
-
|
26
|
+
pageHeaderContainer.style.paddingLeft =
|
27
|
+
'max(1.5rem, env(safe-area-inset-left))';
|
28
|
+
pageHeaderContainer.style.paddingRight =
|
29
|
+
'max(1.5rem, env(safe-area-inset-right))';
|
28
30
|
pageHeaderContainer.style.position = 'fixed';
|
29
31
|
pageHeaderContainer.style.top = props.topOffset || '0';
|
30
32
|
|
@@ -16,7 +16,8 @@ const theme = require('../theme.js');
|
|
16
16
|
*/
|
17
17
|
function RuntimeErrorHeader(document, root, props) {
|
18
18
|
const header = document.createElement('div');
|
19
|
-
header.innerText =
|
19
|
+
header.innerText =
|
20
|
+
'Error ' + (props.currentErrorIndex + 1) + ' of ' + props.totalErrors;
|
20
21
|
header.style.backgroundColor = '#' + theme.red;
|
21
22
|
header.style.color = '#' + theme.white;
|
22
23
|
header.style.fontWeight = '500';
|
@@ -40,7 +40,8 @@ function RuntimeErrorStack(document, root, props) {
|
|
40
40
|
const currentStack = errorStacks[i];
|
41
41
|
|
42
42
|
const functionName = document.createElement('code');
|
43
|
-
functionName.innerHTML =
|
43
|
+
functionName.innerHTML =
|
44
|
+
' ' + currentStack.functionName || '(anonymous function)';
|
44
45
|
functionName.style.color = '#' + theme.yellow;
|
45
46
|
functionName.style.fontFamily = [
|
46
47
|
'"Operator Mono SSm"',
|
package/client/overlay/index.js
CHANGED
@@ -323,7 +323,10 @@ const debouncedShowRuntimeErrors = utils.debounce(showRuntimeErrors, 30);
|
|
323
323
|
* @returns {boolean} If the error is a Webpack compilation error.
|
324
324
|
*/
|
325
325
|
function isWebpackCompileError(error) {
|
326
|
-
return
|
326
|
+
return (
|
327
|
+
/Module [A-z ]+\(from/.test(error.message) ||
|
328
|
+
/Cannot find module/.test(error.message)
|
329
|
+
);
|
327
330
|
}
|
328
331
|
|
329
332
|
/**
|
@@ -333,7 +336,11 @@ function isWebpackCompileError(error) {
|
|
333
336
|
* @returns {void}
|
334
337
|
*/
|
335
338
|
function handleRuntimeError(error) {
|
336
|
-
if (
|
339
|
+
if (
|
340
|
+
error &&
|
341
|
+
!isWebpackCompileError(error) &&
|
342
|
+
currentRuntimeErrors.indexOf(error) === -1
|
343
|
+
) {
|
337
344
|
currentRuntimeErrors = currentRuntimeErrors.concat(error);
|
338
345
|
}
|
339
346
|
debouncedShowRuntimeErrors(currentRuntimeErrors);
|
@@ -345,4 +352,4 @@ module.exports = Object.freeze({
|
|
345
352
|
handleRuntimeError: handleRuntimeError,
|
346
353
|
showCompileError: showCompileError,
|
347
354
|
showRuntimeErrors: showRuntimeErrors,
|
348
|
-
});
|
355
|
+
});
|
package/client/overlay/utils.js
CHANGED
@@ -59,7 +59,7 @@ function removeAllChildren(element, skip) {
|
|
59
59
|
/** @type {Node[]} */
|
60
60
|
const childList = Array.prototype.slice.call(
|
61
61
|
element.childNodes,
|
62
|
-
typeof skip !== 'undefined' ? skip : 0
|
62
|
+
typeof skip !== 'undefined' ? skip : 0,
|
63
63
|
);
|
64
64
|
|
65
65
|
for (let i = 0; i < childList.length; i += 1) {
|
package/client/reactRefresh.js
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
// Thanks https://github.com/pmmmwh/react-refresh-webpack-plugin
|
2
|
-
const RefreshUtils = require(
|
3
|
-
const RefreshRuntime = require(
|
2
|
+
const RefreshUtils = require('./refreshUtils');
|
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
|
6
6
|
function refresh(moduleId, webpackHot) {
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
7
|
+
const currentExports = RefreshUtils.getModuleExports(moduleId);
|
8
|
+
const fn = (exports) => {
|
9
|
+
RefreshUtils.executeRuntime(exports, moduleId, webpackHot);
|
10
|
+
};
|
11
|
+
if (typeof Promise !== 'undefined' && currentExports instanceof Promise) {
|
12
|
+
currentExports.then(fn);
|
13
|
+
} else {
|
14
|
+
fn(currentExports);
|
15
|
+
}
|
16
16
|
}
|
17
17
|
|
18
18
|
module.exports = {
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
refresh,
|
20
|
+
register: RefreshRuntime.register,
|
21
|
+
createSignatureFunctionForTransform:
|
22
|
+
RefreshRuntime.createSignatureFunctionForTransform,
|
23
23
|
};
|
@@ -8,53 +8,53 @@
|
|
8
8
|
* https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/0b960573797bf38926937994c481e4fec9ed8aa6/LICENSE
|
9
9
|
*/
|
10
10
|
|
11
|
-
var RefreshRuntime = require(
|
11
|
+
var RefreshRuntime = require('react-refresh/runtime');
|
12
12
|
var safeThis = (function () {
|
13
|
-
|
14
|
-
|
13
|
+
// copied from core-js-pure/features/global-this
|
14
|
+
'use strict';
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
var check = function (it) {
|
17
|
+
return it && it.Math == Math && it;
|
18
|
+
};
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
20
|
+
// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
|
21
|
+
// eslint-disable-next-line es/no-global-this -- safe
|
22
|
+
return (
|
23
|
+
check(typeof globalThis == 'object' && globalThis) ||
|
24
|
+
check(typeof window == 'object' && window) ||
|
25
|
+
// eslint-disable-next-line no-restricted-globals -- safe
|
26
|
+
check(typeof self == 'object' && self) ||
|
27
|
+
check(typeof __webpack_require__.g == 'object' && __webpack_require__.g) ||
|
28
|
+
// eslint-disable-next-line no-new-func -- fallback
|
29
|
+
(function () {
|
30
|
+
return this;
|
31
|
+
})() ||
|
32
|
+
this ||
|
33
|
+
Function('return this')()
|
34
|
+
);
|
35
35
|
})();
|
36
36
|
|
37
|
-
if (process.env.NODE_ENV !==
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
37
|
+
if (process.env.NODE_ENV !== 'production') {
|
38
|
+
if (typeof safeThis !== 'undefined') {
|
39
|
+
var $RefreshInjected$ = '__reactRefreshInjected';
|
40
|
+
// Namespace the injected flag (if necessary) for monorepo compatibility
|
41
|
+
if (
|
42
|
+
typeof __react_refresh_library__ !== 'undefined' &&
|
43
|
+
__react_refresh_library__
|
44
|
+
) {
|
45
|
+
$RefreshInjected$ += '_' + __react_refresh_library__;
|
46
|
+
}
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
// Only inject the runtime if it hasn't been injected
|
49
|
+
if (!safeThis[$RefreshInjected$]) {
|
50
|
+
RefreshRuntime.injectIntoGlobalHook(safeThis);
|
51
51
|
|
52
|
-
|
53
|
-
|
54
|
-
|
52
|
+
// Empty implementation to avoid "ReferenceError: variable is not defined" in module which didn't pass builtin:react-refresh-loader
|
53
|
+
safeThis.$RefreshSig$ = () => (type) => type;
|
54
|
+
safeThis.$RefreshReg$ = () => {};
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
// Mark the runtime as injected to prevent double-injection
|
57
|
+
safeThis[$RefreshInjected$] = true;
|
58
|
+
}
|
59
|
+
}
|
60
60
|
}
|