Skip to content

Commit 9e65c24

Browse files
feat: improve host output and fix open (#2892)
1 parent 763cde1 commit 9e65c24

File tree

6 files changed

+224
-69
lines changed

6 files changed

+224
-69
lines changed

lib/Server.js

+82-7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const url = require('url');
66
const http = require('http');
77
const https = require('https');
88
const ip = require('ip');
9+
const internalIp = require('internal-ip');
910
const killable = require('killable');
1011
const chokidar = require('chokidar');
1112
const express = require('express');
@@ -21,8 +22,8 @@ const { validate } = require('schema-utils');
2122
const normalizeOptions = require('./utils/normalizeOptions');
2223
const updateCompiler = require('./utils/updateCompiler');
2324
const getCertificate = require('./utils/getCertificate');
24-
const status = require('./utils/status');
25-
const createDomain = require('./utils/createDomain');
25+
const colors = require('./utils/colors');
26+
const runOpen = require('./utils/runOpen');
2627
const runBonjour = require('./utils/runBonjour');
2728
const routes = require('./utils/routes');
2829
const getSocketServerImplementation = require('./utils/getSocketServerImplementation');
@@ -580,17 +581,91 @@ class Server {
580581
}
581582

582583
showStatus() {
583-
const suffix = '/';
584-
const uri = `${createDomain(this.options, this.server)}${suffix}`;
584+
const useColor = getColorsOption(getCompilerConfigArray(this.compiler));
585585

586-
const configArr = getCompilerConfigArray(this.compiler);
587-
const colors = getColorsOption(configArr);
586+
const protocol = this.options.https ? 'https' : 'http';
587+
const { hostname, port } = this;
588+
const prettyPrintUrl = (newHostname) =>
589+
url.format({ protocol, hostname: newHostname, port, pathname: '/' });
590+
591+
let prettyHostname;
592+
let lanUrlForTerminal;
593+
594+
if (hostname === '0.0.0.0' || hostname === '::') {
595+
prettyHostname = 'localhost';
596+
597+
const localIP =
598+
hostname === '::' ? internalIp.v6.sync() : internalIp.v4.sync();
599+
600+
if (localIP) {
601+
lanUrlForTerminal = prettyPrintUrl(localIP);
602+
}
603+
} else {
604+
prettyHostname = hostname;
605+
}
588606

589-
status(uri, this.options, this.logger, colors);
607+
const localUrlForTerminal = prettyPrintUrl(prettyHostname);
608+
609+
if (lanUrlForTerminal) {
610+
this.logger.info('Project is running at:');
611+
this.logger.info(`Local: ${colors.info(useColor, localUrlForTerminal)}`);
612+
this.logger.info(
613+
`On Your Network: ${colors.info(useColor, lanUrlForTerminal)}`
614+
);
615+
} else {
616+
this.logger.info(
617+
`Project is running at ${colors.info(useColor, localUrlForTerminal)}`
618+
);
619+
}
620+
621+
if (
622+
this.options.dev &&
623+
typeof this.options.dev.publicPath !== 'undefined'
624+
) {
625+
this.options.info(
626+
`webpack output is served from '${colors.info(
627+
useColor,
628+
this.options.dev.publicPath === 'auto'
629+
? '/'
630+
: this.options.dev.publicPath
631+
)}' URL`
632+
);
633+
}
634+
635+
if (this.options.static && this.options.static.length > 0) {
636+
this.logger.info(
637+
`Content not from webpack is served from '${colors.info(
638+
useColor,
639+
this.options.static
640+
.map((staticOption) => staticOption.directory)
641+
.join(', ')
642+
)}' directory`
643+
);
644+
}
645+
646+
if (this.options.historyApiFallback) {
647+
this.logger.info(
648+
`404s will fallback to '${colors.info(
649+
useColor,
650+
this.options.historyApiFallback.index || '/index.html'
651+
)}'`
652+
);
653+
}
654+
655+
if (this.options.bonjour) {
656+
this.logger.info(
657+
'Broadcasting "http" with subtype of "webpack" via ZeroConf DNS (Bonjour)'
658+
);
659+
}
660+
661+
if (this.options.open) {
662+
runOpen(localUrlForTerminal, this.options, this.logger);
663+
}
590664
}
591665

592666
listen(port, hostname, fn) {
593667
this.hostname = hostname;
668+
594669
if (typeof port !== 'undefined' && port !== this.options.port) {
595670
this.logger.warn(
596671
'The port specified in options and the port passed as an argument is different.'

lib/utils/createDomain.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,27 @@ function createDomain(options, server) {
88
// use location hostname and port by default in createSocketUrl
99
// ipv6 detection is not required as 0.0.0.0 is just used as a placeholder
1010
let hostname;
11+
1112
if (options.useLocalIp) {
1213
hostname = ip.v4.sync() || '0.0.0.0';
1314
} else if (server) {
1415
hostname = server.address().address;
1516
} else {
1617
hostname = '0.0.0.0';
1718
}
19+
1820
const port = server ? server.address().port : 0;
21+
1922
// use explicitly defined public url
2023
// (prefix with protocol if not explicitly given)
2124
if (options.public) {
2225
return /^[a-zA-Z]+:\/\//.test(options.public)
2326
? `${options.public}`
2427
: `${protocol}://${options.public}`;
2528
}
29+
2630
// the formatted domain (url without path) of the webpack server
27-
return url.format({
28-
protocol,
29-
hostname,
30-
port,
31-
});
31+
return url.format({ protocol, hostname, port });
3232
}
3333

3434
module.exports = createDomain;

lib/utils/status.js

-47
This file was deleted.

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

33
exports[`CLI --hot webpack 4 1`] = `
4-
"<i> [webpack-dev-server] Project is running at http://127.0.0.1:8080/
4+
"<i> [webpack-dev-server] Project is running at http://localhost:8080/
55
<i> [webpack-dev-middleware] Hash: X
66
<i> Version: webpack x.x.x Time: Xms
77
<i> Built at: Thu Jan 01 1970 <CLR=BOLD>00:00:00</CLR> GMT
@@ -28,7 +28,7 @@ exports[`CLI --hot webpack 4 1`] = `
2828
`;
2929
3030
exports[`CLI --hot webpack 5 1`] = `
31-
"<i> [webpack-dev-server] Project is running at http://127.0.0.1:8080/
31+
"<i> [webpack-dev-server] Project is running at http://localhost:8080/
3232
<i> [webpack-dev-middleware] asset main.js X KiB [emitted] (name: main)
3333
<i> runtime modules X KiB 10 modules
3434
<i> cacheable modules X KiB
@@ -46,7 +46,7 @@ exports[`CLI --hot webpack 5 1`] = `
4646
`;
4747
4848
exports[`CLI --no-hot webpack 4 1`] = `
49-
"<i> [webpack-dev-server] Project is running at http://127.0.0.1:8080/
49+
"<i> [webpack-dev-server] Project is running at http://localhost:8080/
5050
<i> [webpack-dev-middleware] Hash: X
5151
<i> Version: webpack x.x.x Time: Xms
5252
<i> Built at: Thu Jan 01 1970 <CLR=BOLD>00:00:00</CLR> GMT
@@ -73,7 +73,7 @@ exports[`CLI --no-hot webpack 4 1`] = `
7373
`;
7474
7575
exports[`CLI --no-hot webpack 5 1`] = `
76-
"<i> [webpack-dev-server] Project is running at http://127.0.0.1:8080/
76+
"<i> [webpack-dev-server] Project is running at http://localhost:8080/
7777
<i> [webpack-dev-middleware] asset main.js X KiB [emitted] (name: main)
7878
<i> runtime modules X bytes 3 modules
7979
<i> cacheable modules X KiB

test/cli/cli.test.js

+50-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
const { join, resolve } = require('path');
44
const execa = require('execa');
5+
const internalIp = require('internal-ip');
56
const testBin = require('../helpers/test-bin');
67
const isWebpack5 = require('../helpers/isWebpack5');
78

@@ -118,12 +119,57 @@ runCLITest('CLI', () => {
118119
.catch(done);
119120
});
120121

121-
it('unspecified port', (done) => {
122+
it('unspecified host and port', (done) => {
122123
testBin('')
123124
.then((output) => {
124-
expect(/http:\/\/127\.0\.0\.1:[0-9]+/.test(output.stderr)).toEqual(
125-
true
126-
);
125+
expect(/http:\/\/localhost:[0-9]+/.test(output.stderr)).toEqual(true);
126+
done();
127+
})
128+
.catch(done);
129+
});
130+
131+
it('--host 0.0.0.0 (IPv4)', (done) => {
132+
testBin('--host 0.0.0.0')
133+
.then((output) => {
134+
const localIP = internalIp.v4.sync();
135+
136+
expect(/http:\/\/localhost:[0-9]+/.test(output.stderr)).toEqual(true);
137+
expect(
138+
new RegExp(`http://${localIP}:[0-9]+/`).test(output.stderr)
139+
).toEqual(true);
140+
done();
141+
})
142+
.catch(done);
143+
});
144+
145+
// TODO search way how to tests it on github actions
146+
it.skip('--host :: (IPv6)', (done) => {
147+
testBin('--host ::')
148+
.then((output) => {
149+
const localIP = internalIp.v4.sync();
150+
151+
expect(/http:\/\/localhost:[0-9]+/.test(output.stderr)).toEqual(true);
152+
expect(
153+
new RegExp(`http://${localIP}:[0-9]+/`).test(output.stderr)
154+
).toEqual(true);
155+
done();
156+
})
157+
.catch(done);
158+
});
159+
160+
it('--host localhost', (done) => {
161+
testBin('--host localhost')
162+
.then((output) => {
163+
expect(/http:\/\/localhost:[0-9]+/.test(output.stderr)).toEqual(true);
164+
done();
165+
})
166+
.catch(done);
167+
});
168+
169+
it('--port', (done) => {
170+
testBin('--port 9999')
171+
.then((output) => {
172+
expect(/http:\/\/localhost:9999/.test(output.stderr)).toEqual(true);
127173
done();
128174
})
129175
.catch(done);

0 commit comments

Comments
 (0)