@rspack/plugin-react-refresh 1.0.0-alpha.0 → 1.0.0-alpha.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/client/errorOverlayEntry.js +108 -0
- package/client/overlay/components/CompileErrorTrace.js +58 -0
- package/client/overlay/components/PageHeader.js +58 -0
- package/client/overlay/components/RuntimeErrorFooter.js +93 -0
- package/client/overlay/components/RuntimeErrorHeader.js +37 -0
- package/client/overlay/components/RuntimeErrorStack.js +79 -0
- package/client/overlay/components/Spacer.js +19 -0
- package/client/overlay/containers/CompileErrorContainer.js +25 -0
- package/client/overlay/containers/RuntimeErrorContainer.js +29 -0
- package/client/overlay/index.js +348 -0
- package/client/overlay/theme.js +39 -0
- package/client/overlay/utils.js +74 -0
- package/client/utils/ansi-html.js +305 -0
- package/client/utils/errorEventHandlers.js +102 -0
- package/client/utils/formatWebpackErrors.js +96 -0
- package/client/utils/retry.js +23 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +33 -3
- package/dist/options.d.ts +16 -1
- package/dist/options.js +19 -0
- package/dist/sockets/WDSSocket.d.ts +10 -0
- package/dist/sockets/WDSSocket.js +41 -0
- package/dist/sockets/utils/getCurrentScriptSource.d.ts +1 -0
- package/dist/sockets/utils/getCurrentScriptSource.js +26 -0
- package/dist/sockets/utils/getSocketUrlParts.d.ts +9 -0
- package/dist/sockets/utils/getSocketUrlParts.js +112 -0
- package/dist/sockets/utils/getUrlFromParts.d.ts +9 -0
- package/dist/sockets/utils/getUrlFromParts.js +32 -0
- package/dist/sockets/utils/getWDSMetadata.d.ts +5 -0
- package/dist/sockets/utils/getWDSMetadata.js +30 -0
- package/dist/utils/getAdditionalEntries.d.ts +9 -0
- package/dist/utils/getAdditionalEntries.js +93 -0
- package/dist/utils/getSocketIntegration.d.ts +2 -0
- package/dist/utils/getSocketIntegration.js +17 -0
- package/package.json +7 -3
@@ -0,0 +1,41 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.init = void 0;
|
7
|
+
/**
|
8
|
+
* The following code is modified based on
|
9
|
+
* https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/f1c8b9a44198449093ca95f85af5df97925e1cfc/sockets/WPSSocket.js
|
10
|
+
*
|
11
|
+
* MIT Licensed
|
12
|
+
* Author Michael Mok
|
13
|
+
* Copyright (c) 2019 Michael Mok
|
14
|
+
* https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/0b960573797bf38926937994c481e4fec9ed8aa6/LICENSE
|
15
|
+
*/
|
16
|
+
const getSocketUrlParts_1 = __importDefault(require("./utils/getSocketUrlParts"));
|
17
|
+
const getUrlFromParts_1 = __importDefault(require("./utils/getUrlFromParts"));
|
18
|
+
const getWDSMetadata_1 = __importDefault(require("./utils/getWDSMetadata"));
|
19
|
+
/**
|
20
|
+
* Initializes a socket server for HMR for webpack-dev-server.
|
21
|
+
* @param {function(*): void} messageHandler A handler to consume Webpack compilation messages.
|
22
|
+
* @param {string} [resourceQuery] Webpack's `__resourceQuery` string.
|
23
|
+
* @returns {void}
|
24
|
+
*/
|
25
|
+
function init(messageHandler, resourceQuery) {
|
26
|
+
if (typeof __webpack_dev_server_client__ !== "undefined") {
|
27
|
+
let SocketClient = __webpack_dev_server_client__;
|
28
|
+
if (typeof __webpack_dev_server_client__.default !== "undefined") {
|
29
|
+
SocketClient = __webpack_dev_server_client__.default;
|
30
|
+
}
|
31
|
+
const wdsMeta = (0, getWDSMetadata_1.default)(SocketClient);
|
32
|
+
const urlParts = (0, getSocketUrlParts_1.default)(resourceQuery, wdsMeta);
|
33
|
+
const connection = new SocketClient((0, getUrlFromParts_1.default)(urlParts, wdsMeta));
|
34
|
+
// @ts-expect-error -- ignore
|
35
|
+
connection.onMessage(function onSocketMessage(data) {
|
36
|
+
const message = JSON.parse(data);
|
37
|
+
messageHandler(message);
|
38
|
+
});
|
39
|
+
}
|
40
|
+
}
|
41
|
+
exports.init = init;
|
@@ -0,0 +1 @@
|
|
1
|
+
export default function getCurrentScriptSource(): any;
|
@@ -0,0 +1,26 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
function getCurrentScriptSource() {
|
4
|
+
// `document.currentScript` is the most accurate way to get the current running script,
|
5
|
+
// but is not supported in all browsers (most notably, IE).
|
6
|
+
if ("currentScript" in document) {
|
7
|
+
// In some cases, `document.currentScript` would be `null` even if the browser supports it:
|
8
|
+
// e.g. asynchronous chunks on Firefox.
|
9
|
+
// We should not fallback to the list-approach as it would not be safe.
|
10
|
+
if (document.currentScript == null)
|
11
|
+
return;
|
12
|
+
return document.currentScript.getAttribute("src");
|
13
|
+
}
|
14
|
+
else {
|
15
|
+
// Fallback to getting all scripts running in the document,
|
16
|
+
// and finding the last one injected.
|
17
|
+
const scriptElementsWithSrc = Array.prototype.filter.call(document.scripts || [], function (elem) {
|
18
|
+
return elem.getAttribute("src");
|
19
|
+
});
|
20
|
+
if (!scriptElementsWithSrc.length)
|
21
|
+
return;
|
22
|
+
const currentScript = scriptElementsWithSrc[scriptElementsWithSrc.length - 1];
|
23
|
+
return currentScript.getAttribute("src");
|
24
|
+
}
|
25
|
+
}
|
26
|
+
exports.default = getCurrentScriptSource;
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { WDSMetaObj } from "./getWDSMetadata";
|
2
|
+
export interface SocketUrlParts {
|
3
|
+
auth?: string;
|
4
|
+
hostname: string;
|
5
|
+
protocol?: string;
|
6
|
+
pathname: string;
|
7
|
+
port?: string;
|
8
|
+
}
|
9
|
+
export default function getSocketUrlParts(resourceQuery?: string, metadata?: WDSMetaObj): SocketUrlParts;
|
@@ -0,0 +1,112 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
const getCurrentScriptSource_1 = __importDefault(require("./getCurrentScriptSource"));
|
7
|
+
function getSocketUrlParts(resourceQuery, metadata) {
|
8
|
+
if (typeof metadata === "undefined") {
|
9
|
+
metadata = {};
|
10
|
+
}
|
11
|
+
/** @type {SocketUrlParts} */
|
12
|
+
let urlParts = {};
|
13
|
+
// If the resource query is available,
|
14
|
+
// parse it and ignore everything we received from the script host.
|
15
|
+
if (resourceQuery) {
|
16
|
+
const parsedQuery = {};
|
17
|
+
const searchParams = new URLSearchParams(resourceQuery.slice(1));
|
18
|
+
searchParams.forEach(function (value, key) {
|
19
|
+
// @ts-expect-error -- ignore
|
20
|
+
parsedQuery[key] = value;
|
21
|
+
});
|
22
|
+
urlParts.hostname = parsedQuery.sockHost;
|
23
|
+
urlParts.pathname = parsedQuery.sockPath;
|
24
|
+
urlParts.port = parsedQuery.sockPort;
|
25
|
+
// Make sure the protocol from resource query has a trailing colon
|
26
|
+
if (parsedQuery.sockProtocol) {
|
27
|
+
urlParts.protocol = parsedQuery.sockProtocol + ":";
|
28
|
+
}
|
29
|
+
}
|
30
|
+
else {
|
31
|
+
const scriptSource = (0, getCurrentScriptSource_1.default)();
|
32
|
+
let url = {};
|
33
|
+
try {
|
34
|
+
// The placeholder `baseURL` with `window.location.href`,
|
35
|
+
// is to allow parsing of path-relative or protocol-relative URLs,
|
36
|
+
// and will have no effect if `scriptSource` is a fully valid URL.
|
37
|
+
url = new URL(scriptSource, window.location.href);
|
38
|
+
}
|
39
|
+
catch (e) {
|
40
|
+
// URL parsing failed, do nothing.
|
41
|
+
// We will still proceed to see if we can recover using `resourceQuery`
|
42
|
+
}
|
43
|
+
// Parse authentication credentials in case we need them
|
44
|
+
if (url.username) {
|
45
|
+
// Since HTTP basic authentication does not allow empty username,
|
46
|
+
// we only include password if the username is not empty.
|
47
|
+
// Result: <username> or <username>:<password>
|
48
|
+
urlParts.auth = url.username;
|
49
|
+
if (url.password) {
|
50
|
+
urlParts.auth += ":" + url.password;
|
51
|
+
}
|
52
|
+
}
|
53
|
+
// `file://` URLs has `'null'` origin
|
54
|
+
if (url.origin !== "null") {
|
55
|
+
urlParts.hostname = url.hostname;
|
56
|
+
}
|
57
|
+
urlParts.protocol = url.protocol;
|
58
|
+
urlParts.port = url.port;
|
59
|
+
}
|
60
|
+
if (!urlParts.pathname) {
|
61
|
+
if (metadata.version === 4) {
|
62
|
+
// This is hard-coded in WDS v4
|
63
|
+
urlParts.pathname = "/ws";
|
64
|
+
}
|
65
|
+
else {
|
66
|
+
// This is hard-coded in WDS v3
|
67
|
+
urlParts.pathname = "/sockjs-node";
|
68
|
+
}
|
69
|
+
}
|
70
|
+
// Check for IPv4 and IPv6 host addresses that correspond to any/empty.
|
71
|
+
// This is important because `hostname` can be empty for some hosts,
|
72
|
+
// such as 'about:blank' or 'file://' URLs.
|
73
|
+
const isEmptyHostname = urlParts.hostname === "0.0.0.0" ||
|
74
|
+
urlParts.hostname === "[::]" ||
|
75
|
+
!urlParts.hostname;
|
76
|
+
// We only re-assign the hostname if it is empty,
|
77
|
+
// and if we are using HTTP/HTTPS protocols.
|
78
|
+
if (isEmptyHostname &&
|
79
|
+
window.location.hostname &&
|
80
|
+
window.location.protocol.indexOf("http") === 0) {
|
81
|
+
urlParts.hostname = window.location.hostname;
|
82
|
+
}
|
83
|
+
// We only re-assign `protocol` when `protocol` is unavailable,
|
84
|
+
// or if `hostname` is available and is empty,
|
85
|
+
// since otherwise we risk creating an invalid URL.
|
86
|
+
// We also do this when 'https' is used as it mandates the use of secure sockets.
|
87
|
+
if (!urlParts.protocol ||
|
88
|
+
(urlParts.hostname &&
|
89
|
+
(isEmptyHostname || window.location.protocol === "https:"))) {
|
90
|
+
urlParts.protocol = window.location.protocol;
|
91
|
+
}
|
92
|
+
// We only re-assign port when it is not available
|
93
|
+
if (!urlParts.port) {
|
94
|
+
urlParts.port = window.location.port;
|
95
|
+
}
|
96
|
+
if (!urlParts.hostname || !urlParts.pathname) {
|
97
|
+
throw new Error([
|
98
|
+
"[React Refresh] Failed to get an URL for the socket connection.",
|
99
|
+
"This usually means that the current executed script doesn't have a `src` attribute set.",
|
100
|
+
"You should either specify the socket path parameters under the `devServer` key in your Rspack config, or use the `overlay` option.",
|
101
|
+
"https://www.rspack.dev/guide/tech/react#fast-refresh"
|
102
|
+
].join("\n"));
|
103
|
+
}
|
104
|
+
return {
|
105
|
+
auth: urlParts.auth,
|
106
|
+
hostname: urlParts.hostname,
|
107
|
+
pathname: urlParts.pathname,
|
108
|
+
protocol: urlParts.protocol,
|
109
|
+
port: urlParts.port || undefined
|
110
|
+
};
|
111
|
+
}
|
112
|
+
exports.default = getSocketUrlParts;
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import type { SocketUrlParts } from "./getSocketUrlParts";
|
2
|
+
import type { WDSMetaObj } from "./getWDSMetadata";
|
3
|
+
/**
|
4
|
+
* Create a valid URL from parsed URL parts.
|
5
|
+
* @param {import('./getSocketUrlParts').SocketUrlParts} urlParts The parsed URL parts.
|
6
|
+
* @param {import('./getWDSMetadata').WDSMetaObj} [metadata] The parsed WDS metadata object.
|
7
|
+
* @returns {string} The generated URL.
|
8
|
+
*/
|
9
|
+
export default function urlFromParts(urlParts: SocketUrlParts, metadata: WDSMetaObj): string;
|
@@ -0,0 +1,32 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
/**
|
4
|
+
* Create a valid URL from parsed URL parts.
|
5
|
+
* @param {import('./getSocketUrlParts').SocketUrlParts} urlParts The parsed URL parts.
|
6
|
+
* @param {import('./getWDSMetadata').WDSMetaObj} [metadata] The parsed WDS metadata object.
|
7
|
+
* @returns {string} The generated URL.
|
8
|
+
*/
|
9
|
+
function urlFromParts(urlParts, metadata) {
|
10
|
+
if (typeof metadata === "undefined") {
|
11
|
+
metadata = {};
|
12
|
+
}
|
13
|
+
let fullProtocol = "http:";
|
14
|
+
if (urlParts.protocol) {
|
15
|
+
fullProtocol = urlParts.protocol;
|
16
|
+
}
|
17
|
+
if (metadata.enforceWs) {
|
18
|
+
fullProtocol = fullProtocol.replace(/^(?:http|.+-extension|file)/i, "ws");
|
19
|
+
}
|
20
|
+
fullProtocol = fullProtocol + "//";
|
21
|
+
let fullHost = urlParts.hostname;
|
22
|
+
if (urlParts.auth) {
|
23
|
+
const fullAuth = urlParts.auth.split(":").map(encodeURIComponent).join(":") + "@";
|
24
|
+
fullHost = fullAuth + fullHost;
|
25
|
+
}
|
26
|
+
if (urlParts.port) {
|
27
|
+
fullHost = fullHost + ":" + urlParts.port;
|
28
|
+
}
|
29
|
+
const url = new URL(urlParts.pathname, fullProtocol + fullHost);
|
30
|
+
return url.href;
|
31
|
+
}
|
32
|
+
exports.default = urlFromParts;
|
@@ -0,0 +1,30 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
function getWDSMetadata(SocketClient) {
|
4
|
+
let enforceWs = false;
|
5
|
+
if (typeof SocketClient.name !== "undefined" &&
|
6
|
+
SocketClient.name !== null &&
|
7
|
+
SocketClient.name.toLowerCase().includes("websocket")) {
|
8
|
+
enforceWs = true;
|
9
|
+
}
|
10
|
+
let version;
|
11
|
+
// WDS versions <=3.5.0
|
12
|
+
if (!("onMessage" in SocketClient.prototype)) {
|
13
|
+
version = 3;
|
14
|
+
}
|
15
|
+
else {
|
16
|
+
// WDS versions >=3.5.0 <4
|
17
|
+
if ("getClientPath" in SocketClient ||
|
18
|
+
Object.getPrototypeOf(SocketClient).name === "BaseClient") {
|
19
|
+
version = 3;
|
20
|
+
}
|
21
|
+
else {
|
22
|
+
version = 4;
|
23
|
+
}
|
24
|
+
}
|
25
|
+
return {
|
26
|
+
enforceWs: enforceWs,
|
27
|
+
version: version
|
28
|
+
};
|
29
|
+
}
|
30
|
+
exports.default = getWDSMetadata;
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import type { NormalizedPluginOptions } from "../options";
|
2
|
+
export interface AdditionalEntries {
|
3
|
+
prependEntries: string[];
|
4
|
+
overlayEntries: string[];
|
5
|
+
}
|
6
|
+
export declare function getAdditionalEntries({ devServer, options }: {
|
7
|
+
devServer: any;
|
8
|
+
options: NormalizedPluginOptions;
|
9
|
+
}): AdditionalEntries;
|
@@ -0,0 +1,93 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.getAdditionalEntries = void 0;
|
7
|
+
const node_querystring_1 = __importDefault(require("node:querystring"));
|
8
|
+
function getAdditionalEntries({ devServer, options }) {
|
9
|
+
/** @type {Record<string, string | number>} */
|
10
|
+
let resourceQuery = {};
|
11
|
+
if (devServer) {
|
12
|
+
const { client, https, http2, sockHost, sockPath, sockPort } = devServer;
|
13
|
+
let { host, path, port } = devServer;
|
14
|
+
let protocol = https || http2 ? "https" : "http";
|
15
|
+
if (sockHost)
|
16
|
+
host = sockHost;
|
17
|
+
if (sockPath)
|
18
|
+
path = sockPath;
|
19
|
+
if (sockPort)
|
20
|
+
port = sockPort;
|
21
|
+
if (client && client.webSocketURL != null) {
|
22
|
+
let parsedUrl = client.webSocketURL;
|
23
|
+
if (typeof parsedUrl === "string")
|
24
|
+
parsedUrl = new URL(parsedUrl);
|
25
|
+
let auth;
|
26
|
+
if (parsedUrl.username) {
|
27
|
+
auth = parsedUrl.username;
|
28
|
+
if (parsedUrl.password) {
|
29
|
+
auth += ":" + parsedUrl.password;
|
30
|
+
}
|
31
|
+
}
|
32
|
+
if (parsedUrl.hostname != null) {
|
33
|
+
host = [auth != null && auth, parsedUrl.hostname]
|
34
|
+
.filter(Boolean)
|
35
|
+
.join("@");
|
36
|
+
}
|
37
|
+
if (parsedUrl.pathname != null) {
|
38
|
+
path = parsedUrl.pathname;
|
39
|
+
}
|
40
|
+
if (parsedUrl.port != null) {
|
41
|
+
port = !["0", "auto"].includes(String(parsedUrl.port))
|
42
|
+
? parsedUrl.port
|
43
|
+
: undefined;
|
44
|
+
}
|
45
|
+
if (parsedUrl.protocol != null) {
|
46
|
+
protocol =
|
47
|
+
parsedUrl.protocol !== "auto"
|
48
|
+
? parsedUrl.protocol.replace(":", "")
|
49
|
+
: "ws";
|
50
|
+
}
|
51
|
+
}
|
52
|
+
if (host)
|
53
|
+
resourceQuery.sockHost = host;
|
54
|
+
if (path)
|
55
|
+
resourceQuery.sockPath = path;
|
56
|
+
if (port)
|
57
|
+
resourceQuery.sockPort = port;
|
58
|
+
resourceQuery.sockProtocol = protocol;
|
59
|
+
}
|
60
|
+
if (options.overlay) {
|
61
|
+
const { sockHost, sockPath, sockPort, sockProtocol } = options.overlay;
|
62
|
+
if (sockHost)
|
63
|
+
resourceQuery.sockHost = sockHost;
|
64
|
+
if (sockPath)
|
65
|
+
resourceQuery.sockPath = sockPath;
|
66
|
+
if (sockPort)
|
67
|
+
resourceQuery.sockPort = sockPort;
|
68
|
+
if (sockProtocol)
|
69
|
+
resourceQuery.sockProtocol = sockProtocol;
|
70
|
+
}
|
71
|
+
// We don't need to URI encode the resourceQuery as it will be parsed by Webpack
|
72
|
+
const queryString = node_querystring_1.default.stringify(resourceQuery, undefined, undefined, {
|
73
|
+
/**
|
74
|
+
* @param {string} string
|
75
|
+
* @returns {string}
|
76
|
+
*/
|
77
|
+
encodeURIComponent(string) {
|
78
|
+
return string;
|
79
|
+
}
|
80
|
+
});
|
81
|
+
const prependEntries = [
|
82
|
+
// React-refresh runtime
|
83
|
+
require.resolve("../../client/reactRefreshEntry")
|
84
|
+
];
|
85
|
+
const overlayEntries = [
|
86
|
+
// Error overlay runtime
|
87
|
+
options.overlay &&
|
88
|
+
options.overlay.entry &&
|
89
|
+
`${require.resolve(options.overlay.entry)}${queryString ? `?${queryString}` : ""}`
|
90
|
+
].filter(Boolean);
|
91
|
+
return { prependEntries, overlayEntries };
|
92
|
+
}
|
93
|
+
exports.getAdditionalEntries = getAdditionalEntries;
|
@@ -0,0 +1,17 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
function getSocketIntegration(integrationType) {
|
4
|
+
let resolvedSocketIntegration;
|
5
|
+
switch (integrationType) {
|
6
|
+
case "wds": {
|
7
|
+
resolvedSocketIntegration = require.resolve("../sockets/WDSSocket");
|
8
|
+
break;
|
9
|
+
}
|
10
|
+
default: {
|
11
|
+
resolvedSocketIntegration = require.resolve(integrationType);
|
12
|
+
break;
|
13
|
+
}
|
14
|
+
}
|
15
|
+
return resolvedSocketIntegration;
|
16
|
+
}
|
17
|
+
exports.default = getSocketIntegration;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@rspack/plugin-react-refresh",
|
3
|
-
"version": "1.0.0-alpha.
|
3
|
+
"version": "1.0.0-alpha.1",
|
4
4
|
"license": "MIT",
|
5
5
|
"description": "React refresh plugin for rspack",
|
6
6
|
"main": "dist/index.js",
|
@@ -30,8 +30,12 @@
|
|
30
30
|
},
|
31
31
|
"devDependencies": {
|
32
32
|
"react-refresh": "0.14.0",
|
33
|
-
"@rspack/core": "1.0.0-alpha.
|
34
|
-
"@rspack/plugin-react-refresh": "1.0.0-alpha.
|
33
|
+
"@rspack/core": "1.0.0-alpha.1",
|
34
|
+
"@rspack/plugin-react-refresh": "1.0.0-alpha.1"
|
35
|
+
},
|
36
|
+
"dependencies": {
|
37
|
+
"html-entities": "^2.1.0",
|
38
|
+
"error-stack-parser": "^2.0.6"
|
35
39
|
},
|
36
40
|
"peerDependencies": {
|
37
41
|
"react-refresh": ">=0.10.0 <1.0.0"
|