Skip to content

Commit 85c56ba

Browse files
fix: speed up initial client bundling
1 parent acd5100 commit 85c56ba

File tree

2 files changed

+162
-164
lines changed

2 files changed

+162
-164
lines changed

client-src/index.js

Lines changed: 162 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { formatProblem, createOverlay } from "./overlay.js";
77
import { log, logEnabledFeatures, setLogLevel } from "./utils/log.js";
88
import sendMessage from "./utils/sendMessage.js";
99
import reloadApp from "./utils/reloadApp.js";
10-
import createSocketURL from "./utils/createSocketURL.js";
1110
import { isProgressSupported, defineProgressElement } from "./progress.js";
1211

1312
/**
@@ -406,6 +405,168 @@ const onSocketMessage = {
406405
},
407406
};
408407

408+
/**
409+
* @param {{ protocol?: string, auth?: string, hostname?: string, port?: string, pathname?: string, search?: string, hash?: string, slashes?: boolean }} objURL
410+
* @returns {string}
411+
*/
412+
const formatURL = (objURL) => {
413+
let protocol = objURL.protocol || "";
414+
415+
if (protocol && protocol.substr(-1) !== ":") {
416+
protocol += ":";
417+
}
418+
419+
let auth = objURL.auth || "";
420+
421+
if (auth) {
422+
auth = encodeURIComponent(auth);
423+
auth = auth.replace(/%3A/i, ":");
424+
auth += "@";
425+
}
426+
427+
let host = "";
428+
429+
if (objURL.hostname) {
430+
host =
431+
auth +
432+
(objURL.hostname.indexOf(":") === -1
433+
? objURL.hostname
434+
: `[${objURL.hostname}]`);
435+
436+
if (objURL.port) {
437+
host += `:${objURL.port}`;
438+
}
439+
}
440+
441+
let pathname = objURL.pathname || "";
442+
443+
if (objURL.slashes) {
444+
host = `//${host || ""}`;
445+
446+
if (pathname && pathname.charAt(0) !== "/") {
447+
pathname = `/${pathname}`;
448+
}
449+
} else if (!host) {
450+
host = "";
451+
}
452+
453+
let search = objURL.search || "";
454+
455+
if (search && search.charAt(0) !== "?") {
456+
search = `?${search}`;
457+
}
458+
459+
let hash = objURL.hash || "";
460+
461+
if (hash && hash.charAt(0) !== "#") {
462+
hash = `#${hash}`;
463+
}
464+
465+
pathname = pathname.replace(
466+
/[?#]/g,
467+
/**
468+
* @param {string} match
469+
* @returns {string}
470+
*/
471+
(match) => encodeURIComponent(match),
472+
);
473+
search = search.replace("#", "%23");
474+
475+
return `${protocol}${host}${pathname}${search}${hash}`;
476+
};
477+
478+
/**
479+
* @param {URL & { fromCurrentScript?: boolean }} parsedURL
480+
* @returns {string}
481+
*/
482+
const createSocketURL = (parsedURL) => {
483+
let { hostname } = parsedURL;
484+
485+
// Node.js module parses it as `::`
486+
// `new URL(urlString, [baseURLString])` parses it as '[::]'
487+
const isInAddrAny =
488+
hostname === "0.0.0.0" || hostname === "::" || hostname === "[::]";
489+
490+
// why do we need this check?
491+
// hostname n/a for file protocol (example, when using electron, ionic)
492+
// see: https://github.com/webpack/webpack-dev-server/pull/384
493+
if (
494+
isInAddrAny &&
495+
self.location.hostname &&
496+
self.location.protocol.indexOf("http") === 0
497+
) {
498+
hostname = self.location.hostname;
499+
}
500+
501+
let socketURLProtocol = parsedURL.protocol || self.location.protocol;
502+
503+
// When https is used in the app, secure web sockets are always necessary because the browser doesn't accept non-secure web sockets.
504+
if (
505+
socketURLProtocol === "auto:" ||
506+
(hostname && isInAddrAny && self.location.protocol === "https:")
507+
) {
508+
socketURLProtocol = self.location.protocol;
509+
}
510+
511+
socketURLProtocol = socketURLProtocol.replace(
512+
/^(?:http|.+-extension|file)/i,
513+
"ws",
514+
);
515+
516+
let socketURLAuth = "";
517+
518+
// `new URL(urlString, [baseURLstring])` doesn't have `auth` property
519+
// Parse authentication credentials in case we need them
520+
if (parsedURL.username) {
521+
socketURLAuth = parsedURL.username;
522+
523+
// Since HTTP basic authentication does not allow empty username,
524+
// we only include password if the username is not empty.
525+
if (parsedURL.password) {
526+
// Result: <username>:<password>
527+
socketURLAuth = socketURLAuth.concat(":", parsedURL.password);
528+
}
529+
}
530+
531+
// In case the host is a raw IPv6 address, it can be enclosed in
532+
// the brackets as the brackets are needed in the final URL string.
533+
// Need to remove those as url.format blindly adds its own set of brackets
534+
// if the host string contains colons. That would lead to non-working
535+
// double brackets (e.g. [[::]]) host
536+
//
537+
// All of these web socket url params are optionally passed in through resourceQuery,
538+
// so we need to fall back to the default if they are not provided
539+
const socketURLHostname = (
540+
hostname ||
541+
self.location.hostname ||
542+
"localhost"
543+
).replace(/^\[(.*)\]$/, "$1");
544+
545+
let socketURLPort = parsedURL.port;
546+
547+
if (!socketURLPort || socketURLPort === "0") {
548+
socketURLPort = self.location.port;
549+
}
550+
551+
// If path is provided it'll be passed in via the resourceQuery as a
552+
// query param so it has to be parsed out of the querystring in order for the
553+
// client to open the socket to the correct location.
554+
let socketURLPathname = "/ws";
555+
556+
if (parsedURL.pathname && !parsedURL.fromCurrentScript) {
557+
socketURLPathname = parsedURL.pathname;
558+
}
559+
560+
return formatURL({
561+
protocol: socketURLProtocol,
562+
auth: socketURLAuth,
563+
hostname: socketURLHostname,
564+
port: socketURLPort,
565+
pathname: socketURLPathname,
566+
slashes: true,
567+
});
568+
};
569+
409570
const socketURL = createSocketURL(parsedResourceQuery);
410571

411572
socket(socketURL, onSocketMessage, options.reconnect);

client-src/utils/createSocketURL.js

Lines changed: 0 additions & 163 deletions
This file was deleted.

0 commit comments

Comments
 (0)