Skip to content

Commit 32bc877

Browse files
authored
fix: improve processing of CLI flags (#3313)
1 parent 2481a3b commit 32bc877

File tree

5 files changed

+106
-36
lines changed

5 files changed

+106
-36
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,12 @@ Options:
114114
--no-client-progress Do not print compilation progress in percentage in the browser.
115115
--client-overlay Show a full-screen overlay in the browser when there are compiler errors or warnings.
116116
--no-client-overlay Do not show a full-screen overlay in the browser when there are compiler errors or warnings.
117+
--client-logging <value> Log level in the browser (none, error, warn, info, log, verbose).
117118
--open [value...] Open the default browser.
118119
--no-open Do not open the default browser.
119120
--open-app <value> Open specified browser.
120121
--open-target [value...] Open specified route in browser.
121122
--no-open-target Do not open specified route in browser.
122-
--client-logging <value> Log level in the browser (none, error, warn, info, log, verbose).
123123
--history-api-fallback Fallback to /index.html for Single Page Applications.
124124
--no-history-api-fallback Do not fallback to /index.html for Single Page Applications.
125125
--compress Enable gzip compression.

bin/cli-flags.js

+33-31
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use strict';
22

3+
const normalizeOption = (option) => (typeof option === 'object' ? option : {});
4+
35
module.exports = {
46
devServer: [
57
{
@@ -47,7 +49,7 @@ module.exports = {
4749
],
4850
description: 'Directory for static contents.',
4951
processor(opts) {
50-
opts.static = opts.static || {};
52+
opts.static = normalizeOption(opts.static);
5153
opts.static.directory = opts.staticDirectory;
5254
delete opts.staticDirectory;
5355
},
@@ -64,7 +66,7 @@ module.exports = {
6466
'The bundled files will be available in the browser under this path.',
6567
multiple: true,
6668
processor(opts) {
67-
opts.static = opts.static || {};
69+
opts.static = normalizeOption(opts.static);
6870
opts.static.publicPath = opts.staticPublicPath;
6971
delete opts.staticPublicPath;
7072
},
@@ -82,7 +84,7 @@ module.exports = {
8284
'Do not tell dev-server to use serveIndex middleware.',
8385
negative: true,
8486
processor(opts) {
85-
opts.static = opts.static || {};
87+
opts.static = normalizeOption(opts.static);
8688
opts.static.serveIndex = opts.staticServeIndex;
8789
delete opts.staticServeIndex;
8890
},
@@ -99,7 +101,7 @@ module.exports = {
99101
negatedDescription: 'Do not watch for files in static content directory.',
100102
negative: true,
101103
processor(opts) {
102-
opts.static = opts.static || {};
104+
opts.static = normalizeOption(opts.static);
103105
opts.static.watch = opts.staticWatch;
104106
delete opts.staticWatch;
105107
},
@@ -138,7 +140,7 @@ module.exports = {
138140
],
139141
description: 'Passphrase for a pfx file.',
140142
processor(opts) {
141-
opts.https = opts.https || {};
143+
opts.https = normalizeOption(opts.https);
142144
opts.https.passphrase = opts.httpsPassphrase;
143145
delete opts.httpsPassphrase;
144146
},
@@ -153,7 +155,7 @@ module.exports = {
153155
],
154156
description: 'Path to an SSL key.',
155157
processor(opts) {
156-
opts.https = opts.https || {};
158+
opts.https = normalizeOption(opts.https);
157159
opts.https.key = opts.httpsKey;
158160
delete opts.httpsKey;
159161
},
@@ -168,7 +170,7 @@ module.exports = {
168170
],
169171
description: 'Path to an SSL pfx file.',
170172
processor(opts) {
171-
opts.https = opts.https || {};
173+
opts.https = normalizeOption(opts.https);
172174
opts.https.pfx = opts.httpsPfx;
173175
delete opts.httpsPfx;
174176
},
@@ -183,7 +185,7 @@ module.exports = {
183185
],
184186
description: 'Path to an SSL certificate.',
185187
processor(opts) {
186-
opts.https = opts.https || {};
188+
opts.https = normalizeOption(opts.https);
187189
opts.https.cert = opts.httpsCert;
188190
delete opts.httpsCert;
189191
},
@@ -198,7 +200,7 @@ module.exports = {
198200
],
199201
description: 'Path to an SSL CA certificate.',
200202
processor(opts) {
201-
opts.https = opts.https || {};
203+
opts.https = normalizeOption(opts.https);
202204
opts.https.cacert = opts.httpsCacert;
203205
delete opts.httpsCacert;
204206
},
@@ -214,7 +216,7 @@ module.exports = {
214216
description: 'Request for an SSL certificate.',
215217
negatedDescription: 'Do not request for an SSL certificate.',
216218
processor(opts) {
217-
opts.https = opts.https || {};
219+
opts.https = normalizeOption(opts.https);
218220
opts.https.requestCert = opts.httpsRequestCert;
219221
delete opts.httpsRequestCert;
220222
},
@@ -257,7 +259,7 @@ module.exports = {
257259
'Do not tell devServer to inject a Hot Module Replacement entry.',
258260
negative: true,
259261
processor(opts) {
260-
opts.client = opts.client || {};
262+
opts.client = normalizeOption(opts.client);
261263
opts.client.hotEntry = opts.clientHotEntry;
262264
delete opts.clientHotEntry;
263265
},
@@ -275,7 +277,7 @@ module.exports = {
275277
'Do not print compilation progress in percentage in the browser.',
276278
negative: true,
277279
processor(opts) {
278-
opts.client = opts.client || {};
280+
opts.client = normalizeOption(opts.client);
279281
opts.client.progress = opts.clientProgress;
280282
delete opts.clientProgress;
281283
},
@@ -294,11 +296,27 @@ module.exports = {
294296
'Do not show a full-screen overlay in the browser when there are compiler errors or warnings.',
295297
negative: true,
296298
processor(opts) {
297-
opts.client = opts.client || {};
299+
opts.client = normalizeOption(opts.client);
298300
opts.client.overlay = opts.clientOverlay;
299301
delete opts.clientOverlay;
300302
},
301303
},
304+
{
305+
name: 'client-logging',
306+
type: String,
307+
configs: [
308+
{
309+
type: 'string',
310+
},
311+
],
312+
description:
313+
'Log level in the browser (none, error, warn, info, log, verbose).',
314+
processor(opts) {
315+
opts.client = normalizeOption(opts.client);
316+
opts.client.logging = opts.clientLogging;
317+
delete opts.clientLogging;
318+
},
319+
},
302320
{
303321
name: 'open',
304322
type: [Boolean, String],
@@ -325,7 +343,7 @@ module.exports = {
325343
],
326344
description: 'Open specified browser.',
327345
processor(opts) {
328-
opts.open = opts.open || {};
346+
opts.open = normalizeOption(opts.open);
329347
opts.open.app = opts.openApp;
330348
delete opts.openApp;
331349
},
@@ -343,30 +361,14 @@ module.exports = {
343361
],
344362
description: 'Open specified route in browser.',
345363
processor(opts) {
346-
opts.open = opts.open || {};
364+
opts.open = normalizeOption(opts.open);
347365
opts.open.target = opts.openTarget;
348366
delete opts.openTarget;
349367
},
350368
negatedDescription: 'Do not open specified route in browser.',
351369
multiple: true,
352370
negative: true,
353371
},
354-
{
355-
name: 'client-logging',
356-
type: String,
357-
configs: [
358-
{
359-
type: 'string',
360-
},
361-
],
362-
description:
363-
'Log level in the browser (none, error, warn, info, log, verbose).',
364-
processor(opts) {
365-
opts.client = opts.client || {};
366-
opts.client.logging = opts.clientLogging;
367-
delete opts.clientLogging;
368-
},
369-
},
370372
{
371373
name: 'history-api-fallback',
372374
type: Boolean,

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

+10-2
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,14 @@ exports[`CLI --no-https-request-cert 1`] = `
164164
<i> [webpack-dev-server] Content not from webpack is served from '<cwd>/public' directory"
165165
`;
166166

167+
exports[`CLI https and other related options 1`] = `
168+
"<i> [webpack-dev-server] Project is running at:
169+
<i> [webpack-dev-server] Loopback: https://localhost:<port>/
170+
<i> [webpack-dev-server] On Your Network (IPv4): https://<network-ip-v4>:<port>/
171+
<i> [webpack-dev-server] On Your Network (IPv6): https://[<network-ip-v6>]:<port>/
172+
<i> [webpack-dev-server] Content not from webpack is served from '<cwd>/public' directory"
173+
`;
174+
167175
exports[`CLI https options 1`] = `
168176
"<i> [webpack-dev-server] Project is running at:
169177
<i> [webpack-dev-server] Loopback: https://localhost:<port>/
@@ -250,13 +258,13 @@ Options:
250258
--no-client-overlay Do not show a full-screen overlay in the
251259
browser when there are compiler errors or
252260
warnings.
261+
--client-logging <value> Log level in the browser (none, error, warn,
262+
info, log, verbose).
253263
--open [value...] Open the default browser.
254264
--no-open Do not open the default browser.
255265
--open-app <value> Open specified browser.
256266
--open-target [value...] Open specified route in browser.
257267
--no-open-target Do not open specified route in browser.
258-
--client-logging <value> Log level in the browser (none, error, warn,
259-
info, log, verbose).
260268
--history-api-fallback Fallback to /index.html for Single Page
261269
Applications.
262270
--no-history-api-fallback Do not fallback to /index.html for Single

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

+10-2
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,14 @@ exports[`CLI --no-https-request-cert 1`] = `
164164
<i> [webpack-dev-server] Content not from webpack is served from '<cwd>/public' directory"
165165
`;
166166

167+
exports[`CLI https and other related options 1`] = `
168+
"<i> [webpack-dev-server] Project is running at:
169+
<i> [webpack-dev-server] Loopback: https://localhost:<port>/
170+
<i> [webpack-dev-server] On Your Network (IPv4): https://<network-ip-v4>:<port>/
171+
<i> [webpack-dev-server] On Your Network (IPv6): https://[<network-ip-v6>]:<port>/
172+
<i> [webpack-dev-server] Content not from webpack is served from '<cwd>/public' directory"
173+
`;
174+
167175
exports[`CLI https options 1`] = `
168176
"<i> [webpack-dev-server] Project is running at:
169177
<i> [webpack-dev-server] Loopback: https://localhost:<port>/
@@ -251,13 +259,13 @@ Options:
251259
--no-client-overlay Do not show a full-screen overlay in the
252260
browser when there are compiler errors or
253261
warnings.
262+
--client-logging <value> Log level in the browser (none, error, warn,
263+
info, log, verbose).
254264
--open [value...] Open the default browser.
255265
--no-open Do not open the default browser.
256266
--open-app <value> Open specified browser.
257267
--open-target [value...] Open specified route in browser.
258268
--no-open-target Do not open specified route in browser.
259-
--client-logging <value> Log level in the browser (none, error, warn,
260-
info, log, verbose).
261269
--history-api-fallback Fallback to /index.html for Single Page
262270
Applications.
263271
--no-history-api-fallback Do not fallback to /index.html for Single

test/cli/cli.test.js

+52
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,26 @@ describe('CLI', () => {
209209
.catch(done);
210210
});
211211

212+
// For https://github.com/webpack/webpack-dev-server/issues/3306
213+
it('https and other related options', (done) => {
214+
const pfxFile = path.join(httpsCertificateDirectory, 'server.pfx');
215+
const key = path.join(httpsCertificateDirectory, 'server.key');
216+
const cert = path.join(httpsCertificateDirectory, 'server.crt');
217+
const passphrase = 'webpack-dev-server';
218+
219+
testBin(
220+
`--https --https-key ${key} --https-pfx ${pfxFile} --https-passphrase ${passphrase} --https-cert ${cert}`
221+
)
222+
.then((output) => {
223+
expect(output.exitCode).toEqual(0);
224+
expect(
225+
normalizeStderr(output.stderr, { ipv6: true, https: true })
226+
).toMatchSnapshot();
227+
done();
228+
})
229+
.catch(done);
230+
});
231+
212232
it('--https-request-cert', (done) => {
213233
testBin('--https-request-cert')
214234
.then((output) => {
@@ -484,6 +504,15 @@ describe('CLI', () => {
484504
.catch(done);
485505
});
486506

507+
it(' --open --open-target index.html', (done) => {
508+
testBin('--open --open-target index.html')
509+
.then((output) => {
510+
expect(output.exitCode).toEqual(0);
511+
done();
512+
})
513+
.catch(done);
514+
});
515+
487516
it('--open-target /first.html second.html', (done) => {
488517
testBin('--open-target /first.html second.html')
489518
.then((output) => {
@@ -502,6 +531,15 @@ describe('CLI', () => {
502531
.catch(done);
503532
});
504533

534+
it('--open --open-target /index.html --open-app google-chrome', (done) => {
535+
testBin('--open --open-target /index.html --open-app google-chrome')
536+
.then((output) => {
537+
expect(output.exitCode).toEqual(0);
538+
done();
539+
})
540+
.catch(done);
541+
});
542+
505543
it('--client-overlay', (done) => {
506544
testBin('--client-overlay')
507545
.then((output) => {
@@ -593,6 +631,20 @@ describe('CLI', () => {
593631
.catch(done);
594632
});
595633

634+
it('--static --static-directory', (done) => {
635+
testBin(
636+
`--static --static-directory ${path.resolve(
637+
__dirname,
638+
'../fixtures/static/webpack.config.js'
639+
)}`
640+
)
641+
.then((output) => {
642+
expect(output.exitCode).toEqual(0);
643+
done();
644+
})
645+
.catch(done);
646+
});
647+
596648
it('--static-serve-index', (done) => {
597649
testBin('--static-serve-index')
598650
.then((output) => {

0 commit comments

Comments
 (0)