Skip to content

Commit 7e525eb

Browse files
fix: prefer to open the host option (#3115)
1 parent a6eb1a4 commit 7e525eb

File tree

5 files changed

+237
-143
lines changed

5 files changed

+237
-143
lines changed

lib/Server.js

+69-71
Original file line numberDiff line numberDiff line change
@@ -586,92 +586,93 @@ class Server {
586586

587587
showStatus() {
588588
const useColor = getColorsOption(getCompilerConfigArray(this.compiler));
589-
590589
const protocol = this.options.https ? 'https' : 'http';
591-
const { address: hostname, port } = this.server.address();
590+
const { address, port } = this.server.address();
592591
const prettyPrintUrl = (newHostname) =>
593592
url.format({ protocol, hostname: newHostname, port, pathname: '/' });
594593

595-
let localhostForTerminal;
596-
let networkUrlForTerminalIPv4;
597-
let networkUrlForTerminalIPv6;
594+
let server;
595+
let localhost;
596+
let loopbackIPv4;
597+
let loopbackIPv6;
598+
let networkUrlIPv4;
599+
let networkUrlIPv6;
600+
601+
if (this.hostname) {
602+
if (this.hostname === 'localhost') {
603+
localhost = prettyPrintUrl('localhost');
604+
} else {
605+
let isIP;
606+
607+
try {
608+
isIP = ipaddr.parse(this.hostname);
609+
} catch (error) {
610+
// Ignore
611+
}
612+
613+
if (!isIP) {
614+
server = prettyPrintUrl(this.hostname);
615+
}
616+
}
617+
}
598618

599-
const parsedIP = ipaddr.parse(hostname);
600-
const isUnspecified = parsedIP.range() === 'unspecified';
619+
const parsedIP = ipaddr.parse(address);
601620

602-
if (isUnspecified) {
603-
localhostForTerminal = prettyPrintUrl('localhost');
621+
if (parsedIP.range() === 'unspecified') {
622+
localhost = prettyPrintUrl('localhost');
604623

605624
const networkIPv4 = internalIp.v4.sync();
606625

607626
if (networkIPv4) {
608-
networkUrlForTerminalIPv4 = prettyPrintUrl(networkIPv4);
627+
networkUrlIPv4 = prettyPrintUrl(networkIPv4);
609628
}
610629

611-
if (hostname === '::') {
612-
const networkIPv6 = internalIp.v6.sync();
630+
const networkIPv6 = internalIp.v6.sync();
613631

614-
if (networkIPv6) {
615-
networkUrlForTerminalIPv6 = prettyPrintUrl(networkIPv6);
616-
}
632+
if (networkIPv6) {
633+
networkUrlIPv6 = prettyPrintUrl(networkIPv6);
617634
}
618-
} else {
619-
if (parsedIP.range() === 'loopback') {
620-
localhostForTerminal = prettyPrintUrl('localhost');
635+
} else if (parsedIP.range() === 'loopback') {
636+
if (parsedIP.kind() === 'ipv4') {
637+
loopbackIPv4 = prettyPrintUrl(parsedIP.toString());
638+
} else if (parsedIP.kind() === 'ipv6') {
639+
loopbackIPv6 = prettyPrintUrl(parsedIP.toString());
621640
}
641+
} else {
642+
networkUrlIPv4 =
643+
parsedIP.kind() === 'ipv6' && parsedIP.isIPv4MappedAddress()
644+
? prettyPrintUrl(parsedIP.toIPv4Address().toString())
645+
: prettyPrintUrl(address);
622646

623647
if (parsedIP.kind() === 'ipv6') {
624-
if (parsedIP.isIPv4MappedAddress()) {
625-
networkUrlForTerminalIPv4 = prettyPrintUrl(
626-
parsedIP.toIPv4Address().toString()
627-
);
628-
}
629-
} else {
630-
networkUrlForTerminalIPv4 = prettyPrintUrl(hostname);
648+
networkUrlIPv6 = prettyPrintUrl(address);
631649
}
650+
}
632651

633-
if (parsedIP.kind() === 'ipv6') {
634-
networkUrlForTerminalIPv6 = prettyPrintUrl(hostname);
635-
}
652+
this.logger.info('Project is running at:');
653+
654+
if (server) {
655+
this.logger.info(`Server: ${colors.info(useColor, server)}`);
636656
}
637657

638-
if (isUnspecified) {
639-
this.logger.info('Project is running at:');
640-
this.logger.info(`Local: ${colors.info(useColor, localhostForTerminal)}`);
641-
642-
const networkUrlsForTerminal = []
643-
.concat(
644-
networkUrlForTerminalIPv4
645-
? [`${colors.info(useColor, networkUrlForTerminalIPv4)} (IPv4)`]
646-
: []
647-
)
648-
.concat(
649-
networkUrlForTerminalIPv6
650-
? [`${colors.info(useColor, networkUrlForTerminalIPv6)} (IPv6)`]
651-
: []
652-
);
658+
if (localhost || loopbackIPv4 || loopbackIPv6) {
659+
const loopbacks = []
660+
.concat(localhost ? [colors.info(useColor, localhost)] : [])
661+
.concat(loopbackIPv4 ? [colors.info(useColor, loopbackIPv4)] : [])
662+
.concat(loopbackIPv6 ? [colors.info(useColor, loopbackIPv6)] : []);
653663

654-
this.logger.info(`On Your Network: ${networkUrlsForTerminal.join(', ')}`);
655-
} else {
656-
const networkUrlsForTerminal = []
657-
.concat(
658-
localhostForTerminal
659-
? [`${colors.info(useColor, localhostForTerminal)}`]
660-
: []
661-
)
662-
.concat(
663-
networkUrlForTerminalIPv4
664-
? [`${colors.info(useColor, networkUrlForTerminalIPv4)} (IPv4)`]
665-
: []
666-
)
667-
.concat(
668-
networkUrlForTerminalIPv6
669-
? [`${colors.info(useColor, networkUrlForTerminalIPv6)} (IPv6)`]
670-
: []
671-
);
664+
this.logger.info(`Loopback: ${loopbacks.join(', ')}`);
665+
}
666+
667+
if (networkUrlIPv4) {
668+
this.logger.info(
669+
`On Your Network (IPv4): ${colors.info(useColor, networkUrlIPv4)}`
670+
);
671+
}
672672

673+
if (networkUrlIPv6) {
673674
this.logger.info(
674-
`Project is running at ${networkUrlsForTerminal.join(', ')}`
675+
`On Your Network (IPv6): ${colors.info(useColor, networkUrlIPv6)}`
675676
);
676677
}
677678

@@ -716,12 +717,9 @@ class Server {
716717
}
717718

718719
if (this.options.open || this.options.openPage) {
719-
const uri =
720-
localhostForTerminal ||
721-
networkUrlForTerminalIPv4 ||
722-
networkUrlForTerminalIPv6;
720+
const openTarget = prettyPrintUrl(this.hostname || 'localhost');
723721

724-
runOpen(uri, this.options, this.logger);
722+
runOpen(openTarget, this.options, this.logger);
725723
}
726724
}
727725

@@ -740,7 +738,7 @@ class Server {
740738
.then((port) => {
741739
this.port = port;
742740

743-
return this.server.listen(port, hostname, (err) => {
741+
return this.server.listen(port, hostname, (error) => {
744742
if (this.options.hot || this.options.liveReload) {
745743
this.createSocketServer();
746744
}
@@ -752,17 +750,17 @@ class Server {
752750
this.showStatus();
753751

754752
if (fn) {
755-
fn.call(this.server, err);
753+
fn.call(this.server, error);
756754
}
757755

758756
if (typeof this.options.onListening === 'function') {
759757
this.options.onListening(this);
760758
}
761759
});
762760
})
763-
.catch((err) => {
761+
.catch((error) => {
764762
if (fn) {
765-
fn.call(this.server, err);
763+
fn.call(this.server, error);
766764
}
767765
})
768766
);

test/cli/__snapshots__/cli.test.js.snap

+22-12
Original file line numberDiff line numberDiff line change
@@ -2,51 +2,61 @@
22

33
exports[`CLI --host :: (IPv6): stderr 1`] = `
44
"<i> [webpack-dev-server] Project is running at:
5-
<i> [webpack-dev-server] Local: http://localhost:<port>/
6-
<i> [webpack-dev-server] On Your Network: http://<network-ip-v4>:<port>/ (IPv4), http://[<network-ip-v6>]:<port>/ (IPv6)
5+
<i> [webpack-dev-server] Loopback: http://localhost:<port>/
6+
<i> [webpack-dev-server] On Your Network (IPv4): http://<network-ip-v4>:<port>/
7+
<i> [webpack-dev-server] On Your Network (IPv6): http://[<network-ip-v6>]:<port>/
78
<i> [webpack-dev-server] Content not from webpack is served from '<cwd>/public' directory"
89
`;
910
1011
exports[`CLI --host ::1 (IPv6): stderr 1`] = `
11-
"<i> [webpack-dev-server] Project is running at http://localhost:<port>/, http://[::1]:<port>/ (IPv6)
12+
"<i> [webpack-dev-server] Project is running at:
13+
<i> [webpack-dev-server] Loopback: http://[::1]:<port>/
1214
<i> [webpack-dev-server] Content not from webpack is served from '<cwd>/public' directory"
1315
`;
1416
1517
exports[`CLI --host <IPv4>: stderr 1`] = `
16-
"<i> [webpack-dev-server] Project is running at http://<network-ip-v4>:<port>/ (IPv4)
18+
"<i> [webpack-dev-server] Project is running at:
19+
<i> [webpack-dev-server] On Your Network (IPv4): http://<network-ip-v4>:<port>/
1720
<i> [webpack-dev-server] Content not from webpack is served from '<cwd>/public' directory"
1821
`;
1922
2023
exports[`CLI --host 0.0.0.0 (IPv4): stderr 1`] = `
2124
"<i> [webpack-dev-server] Project is running at:
22-
<i> [webpack-dev-server] Local: http://localhost:<port>/
23-
<i> [webpack-dev-server] On Your Network: http://<network-ip-v4>:<port>/ (IPv4)
25+
<i> [webpack-dev-server] Loopback: http://localhost:<port>/
26+
<i> [webpack-dev-server] On Your Network (IPv4): http://<network-ip-v4>:<port>/
27+
<i> [webpack-dev-server] On Your Network (IPv6): http://[<network-ip-v6>]:<port>/
2428
<i> [webpack-dev-server] Content not from webpack is served from '<cwd>/public' directory"
2529
`;
2630
2731
exports[`CLI --host 0:0:0:0:0:FFFF:7F00:0001 (IPv6): stderr 1`] = `
28-
"<i> [webpack-dev-server] Project is running at http://127.0.0.1:<port>/ (IPv4), http://[::ffff:127.0.0.1]:<port>/ (IPv6)
32+
"<i> [webpack-dev-server] Project is running at:
33+
<i> [webpack-dev-server] On Your Network (IPv4): http://127.0.0.1:<port>/
34+
<i> [webpack-dev-server] On Your Network (IPv6): http://[::ffff:127.0.0.1]:<port>/
2935
<i> [webpack-dev-server] Content not from webpack is served from '<cwd>/public' directory"
3036
`;
3137
3238
exports[`CLI --host 127.0.0.1 (IPv4): stderr 1`] = `
33-
"<i> [webpack-dev-server] Project is running at http://localhost:<port>/, http://127.0.0.1:<port>/ (IPv4)
39+
"<i> [webpack-dev-server] Project is running at:
40+
<i> [webpack-dev-server] Loopback: http://127.0.0.1:<port>/
3441
<i> [webpack-dev-server] Content not from webpack is served from '<cwd>/public' directory"
3542
`;
3643
3744
exports[`CLI --host and --port are unspecified: stderr 1`] = `
3845
"<i> [webpack-dev-server] Project is running at:
39-
<i> [webpack-dev-server] Local: http://localhost:<port>/
40-
<i> [webpack-dev-server] On Your Network: http://<network-ip-v4>:<port>/ (IPv4), http://[<network-ip-v6>]:<port>/ (IPv6)
46+
<i> [webpack-dev-server] Loopback: http://localhost:<port>/
47+
<i> [webpack-dev-server] On Your Network (IPv4): http://<network-ip-v4>:<port>/
48+
<i> [webpack-dev-server] On Your Network (IPv6): http://[<network-ip-v6>]:<port>/
4149
<i> [webpack-dev-server] Content not from webpack is served from '<cwd>/public' directory"
4250
`;
4351
4452
exports[`CLI --host localhost --port 9999: stderr 1`] = `
45-
"<i> [webpack-dev-server] Project is running at http://localhost:<port>/, http://127.0.0.1:<port>/ (IPv4)
53+
"<i> [webpack-dev-server] Project is running at:
54+
<i> [webpack-dev-server] Loopback: http://localhost:<port>/, http://127.0.0.1:<port>/
4655
<i> [webpack-dev-server] Content not from webpack is served from '<cwd>/public' directory"
4756
`;
4857
4958
exports[`CLI --host localhost: stderr 1`] = `
50-
"<i> [webpack-dev-server] Project is running at http://localhost:<port>/, http://127.0.0.1:<port>/ (IPv4)
59+
"<i> [webpack-dev-server] Project is running at:
60+
<i> [webpack-dev-server] Loopback: http://localhost:<port>/, http://127.0.0.1:<port>/
5161
<i> [webpack-dev-server] Content not from webpack is served from '<cwd>/public' directory"
5262
`;

test/cli/cli.test.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,9 @@ describe('CLI', () => {
109109
it('--host 0.0.0.0 (IPv4)', (done) => {
110110
testBin('--host 0.0.0.0')
111111
.then((output) => {
112-
expect(normalizeStderr(output.stderr)).toMatchSnapshot('stderr');
112+
expect(normalizeStderr(output.stderr, { ipv6: true })).toMatchSnapshot(
113+
'stderr'
114+
);
113115

114116
done();
115117
})

test/helpers/test-bin.js

+12-3
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,19 @@ function normalizeStderr(stderr, options = {}) {
6262

6363
if (options.ipv6 && !networkIPv6) {
6464
// Github Actions doesnt' support IPv6 on ubuntu in some cases
65-
normalizedStderr = normalizedStderr.replace(
66-
/\(IPv4\)/,
67-
'(IPv4), http://[<network-ip-v6>]:<port>/ (IPv6)'
65+
normalizedStderr = normalizedStderr.split('\n');
66+
67+
const ipv4MessageIndex = normalizedStderr.findIndex((item) =>
68+
/On Your Network \(IPv4\)/.test(item)
6869
);
70+
71+
normalizedStderr.splice(
72+
ipv4MessageIndex + 1,
73+
0,
74+
'<i> [webpack-dev-server] On Your Network (IPv6): http://[<network-ip-v6>]:<port>/'
75+
);
76+
77+
normalizedStderr = normalizedStderr.join('\n');
6978
}
7079

7180
return normalizedStderr;

0 commit comments

Comments
 (0)