1
- const path = require ( 'path' ) ;
2
1
const { program } = require ( 'commander' ) ;
3
2
const getPkg = require ( './utils/package-exists' ) ;
4
3
const webpack = getPkg ( 'webpack' ) ? require ( 'webpack' ) : undefined ;
4
+ const path = require ( 'path' ) ;
5
5
const { merge } = require ( 'webpack-merge' ) ;
6
6
const { extensions, jsVariants } = require ( 'interpret' ) ;
7
7
const rechoir = require ( 'rechoir' ) ;
8
8
const { createWriteStream, existsSync } = require ( 'fs' ) ;
9
9
const { distance } = require ( 'fastest-levenshtein' ) ;
10
10
const { options : coloretteOptions , yellow, cyan, green, bold } = require ( 'colorette' ) ;
11
- const { stringifyStream : createJsonStringifyStream } = require ( '@discoveryjs/json-ext' ) ;
12
11
13
12
const logger = require ( './utils/logger' ) ;
14
13
const { cli, flags } = require ( './utils/cli-flags' ) ;
15
14
const CLIPlugin = require ( './plugins/CLIPlugin' ) ;
16
15
const promptInstallation = require ( './utils/prompt-installation' ) ;
17
-
18
16
const toKebabCase = require ( './utils/to-kebab-case' ) ;
19
17
20
- const { resolve, extname } = path ;
21
-
22
18
class WebpackCLI {
23
19
constructor ( ) {
24
- this . logger = logger ;
25
20
// Initialize program
26
21
this . program = program ;
27
22
this . program . name ( 'webpack' ) ;
28
23
this . program . storeOptionsAsProperties ( false ) ;
24
+ this . webpack = webpack ;
25
+ this . logger = logger ;
29
26
this . utils = { toKebabCase, getPkg, promptInstallation } ;
30
27
}
31
28
@@ -234,6 +231,12 @@ class WebpackCLI {
234
231
description : 'Run webpack (default command, can be omitted).' ,
235
232
usage : '[options]' ,
236
233
} ;
234
+ const watchCommandOptions = {
235
+ name : 'watch' ,
236
+ alias : 'w' ,
237
+ description : 'Run webpack and watch for files changes.' ,
238
+ usage : '[options]' ,
239
+ } ;
237
240
const versionCommandOptions = {
238
241
name : 'version [commands...]' ,
239
242
alias : 'v' ,
@@ -283,7 +286,13 @@ class WebpackCLI {
283
286
} ,
284
287
] ;
285
288
286
- const knownCommands = [ buildCommandOptions , versionCommandOptions , helpCommandOptions , ...externalBuiltInCommandsInfo ] ;
289
+ const knownCommands = [
290
+ buildCommandOptions ,
291
+ watchCommandOptions ,
292
+ versionCommandOptions ,
293
+ helpCommandOptions ,
294
+ ...externalBuiltInCommandsInfo ,
295
+ ] ;
287
296
const getCommandName = ( name ) => name . split ( ' ' ) [ 0 ] ;
288
297
const isKnownCommand = ( name ) =>
289
298
knownCommands . find (
@@ -294,6 +303,9 @@ class WebpackCLI {
294
303
const isBuildCommand = ( name ) =>
295
304
getCommandName ( buildCommandOptions . name ) === name ||
296
305
( Array . isArray ( buildCommandOptions . alias ) ? buildCommandOptions . alias . includes ( name ) : buildCommandOptions . alias === name ) ;
306
+ const isWatchCommand = ( name ) =>
307
+ getCommandName ( watchCommandOptions . name ) === name ||
308
+ ( Array . isArray ( watchCommandOptions . alias ) ? watchCommandOptions . alias . includes ( name ) : watchCommandOptions . alias === name ) ;
297
309
const isHelpCommand = ( name ) =>
298
310
getCommandName ( helpCommandOptions . name ) === name ||
299
311
( Array . isArray ( helpCommandOptions . alias ) ? helpCommandOptions . alias . includes ( name ) : helpCommandOptions . alias === name ) ;
@@ -338,21 +350,40 @@ class WebpackCLI {
338
350
return { commandName : isDefault ? buildCommandOptions . name : commandName , options, isDefault } ;
339
351
} ;
340
352
const loadCommandByName = async ( commandName , allowToInstall = false ) => {
341
- if ( isBuildCommand ( commandName ) ) {
342
- await this . makeCommand ( buildCommandOptions , this . getBuiltInOptions ( ) , async ( program ) => {
343
- const options = program . opts ( ) ;
353
+ const isBuildCommandUsed = isBuildCommand ( commandName ) ;
354
+ const isWatchCommandUsed = isWatchCommand ( commandName ) ;
344
355
345
- if ( program . args . length > 0 ) {
346
- const possibleCommands = [ ] . concat ( [ buildCommandOptions . name ] ) . concat ( program . args ) ;
356
+ if ( isBuildCommandUsed || isWatchCommandUsed ) {
357
+ await this . makeCommand (
358
+ isBuildCommandUsed ? buildCommandOptions : watchCommandOptions ,
359
+ this . getBuiltInOptions ( ) ,
360
+ async ( program ) => {
361
+ const options = program . opts ( ) ;
347
362
348
- logger . error ( 'Running multiple commands at the same time is not possible' ) ;
349
- logger . error ( `Found commands: ${ possibleCommands . map ( ( item ) => `'${ item } '` ) . join ( ', ' ) } ` ) ;
350
- logger . error ( "Run 'webpack --help' to see available commands and options" ) ;
351
- process . exit ( 2 ) ;
352
- }
363
+ if ( program . args . length > 0 ) {
364
+ const possibleCommands = [ ] . concat ( [ buildCommandOptions . name ] ) . concat ( program . args ) ;
353
365
354
- await this . bundleCommand ( options ) ;
355
- } ) ;
366
+ logger . error ( 'Running multiple commands at the same time is not possible' ) ;
367
+ logger . error ( `Found commands: ${ possibleCommands . map ( ( item ) => `'${ item } '` ) . join ( ', ' ) } ` ) ;
368
+ logger . error ( "Run 'webpack --help' to see available commands and options" ) ;
369
+ process . exit ( 2 ) ;
370
+ }
371
+
372
+ if ( isWatchCommandUsed ) {
373
+ if ( typeof options . watch !== 'undefined' ) {
374
+ logger . warn (
375
+ `No need to use the ${
376
+ options . watch ? "'--watch, -w'" : "'--no-watch'"
377
+ } option together with the 'watch' command, it does not make sense`,
378
+ ) ;
379
+ }
380
+
381
+ options . watch = true ;
382
+ }
383
+
384
+ await this . bundleCommand ( options ) ;
385
+ } ,
386
+ ) ;
356
387
} else if ( isHelpCommand ( commandName ) ) {
357
388
// Stub for the `help` command
358
389
this . makeCommand ( helpCommandOptions , [ ] , ( ) => { } ) ;
@@ -492,9 +523,9 @@ class WebpackCLI {
492
523
// Make `-v, --version` options
493
524
// Make `version|v [commands...]` command
494
525
const outputVersion = async ( options ) => {
495
- // Filter `bundle`, `version` and `help` commands
526
+ // Filter `bundle`, `watch`, ` version` and `help` commands
496
527
const possibleCommandNames = options . filter (
497
- ( option ) => ! isBuildCommand ( option ) && ! isVersionCommand ( option ) && ! isHelpCommand ( option ) ,
528
+ ( option ) => ! isBuildCommand ( option ) && ! isWatchCommand ( option ) && ! isVersionCommand ( option ) && ! isHelpCommand ( option ) ,
498
529
) ;
499
530
500
531
possibleCommandNames . forEach ( ( possibleCommandName ) => {
@@ -616,7 +647,7 @@ class WebpackCLI {
616
647
. replace ( buildCommandOptions . description , 'The build tool for modern web applications.' )
617
648
. replace (
618
649
/ U s a g e : .+ / ,
619
- 'Usage: webpack [options]\nAlternative usage: webpack --config <config> [options]\nAlternative usage: webpack build [options]\nAlternative usage: webpack bundle [options]\nAlternative usage: webpack b [options]\nAlternative usage: webpack build --config <config> [options]' ,
650
+ 'Usage: webpack [options]\nAlternative usage: webpack --config <config> [options]\nAlternative usage: webpack build [options]\nAlternative usage: webpack bundle [options]\nAlternative usage: webpack b [options]\nAlternative usage: webpack build --config <config> [options]\nAlternative usage: webpack bundle --config <config> [options]\nAlternative usage: webpack b --config <config> [options] ' ,
620
651
) ;
621
652
622
653
logger . raw ( helpInformation ) ;
@@ -643,25 +674,21 @@ class WebpackCLI {
643
674
let helpInformation = command . helpInformation ( ) . trimRight ( ) ;
644
675
645
676
if ( isBuildCommand ( name ) ) {
646
- helpInformation = helpInformation
647
- . replace ( buildCommandOptions . description , 'The build tool for modern web applications.' )
648
- . replace (
649
- / U s a g e : .+ / ,
650
- 'Usage: webpack [options]\nAlternative usage: webpack --config <config> [options]\nAlternative usage: webpack build [options]\nAlternative usage: webpack bundle [options]\nAlternative usage: webpack b [options]\nAlternative usage: webpack build --config <config> [options]' ,
651
- ) ;
677
+ helpInformation = helpInformation . replace ( 'build|bundle' , 'build|bundle|b' ) ;
652
678
}
653
679
654
680
logger . raw ( helpInformation ) ;
655
681
656
682
outputGlobalOptions ( ) ;
657
683
} else if ( isHelpCommandSyntax ) {
658
- let commandName ;
684
+ let isCommandSpecified = false ;
685
+ let commandName = buildCommandOptions . name ;
659
686
let optionName ;
660
687
661
688
if ( options . length === 1 ) {
662
- commandName = buildCommandOptions . name ;
663
689
optionName = options [ 0 ] ;
664
690
} else if ( options . length === 2 ) {
691
+ isCommandSpecified = true ;
665
692
commandName = options [ 0 ] ;
666
693
optionName = options [ 1 ] ;
667
694
@@ -694,14 +721,10 @@ class WebpackCLI {
694
721
option . flags . replace ( / ^ .+ [ [ < ] / , '' ) . replace ( / ( \. \. \. ) ? [ \] > ] .* $ / , '' ) + ( option . variadic === true ? '...' : '' ) ;
695
722
const value = option . required ? '<' + nameOutput + '>' : option . optional ? '[' + nameOutput + ']' : '' ;
696
723
697
- logger . raw (
698
- `Usage: webpack${ isBuildCommand ( commandName ) ? '' : ` ${ commandName } ` } ${ option . long } ${ value ? ` ${ value } ` : '' } ` ,
699
- ) ;
724
+ logger . raw ( `Usage: webpack${ isCommandSpecified ? ` ${ commandName } ` : '' } ${ option . long } ${ value ? ` ${ value } ` : '' } ` ) ;
700
725
701
726
if ( option . short ) {
702
- logger . raw (
703
- `Short: webpack${ isBuildCommand ( commandName ) ? '' : ` ${ commandName } ` } ${ option . short } ${ value ? ` ${ value } ` : '' } ` ,
704
- ) ;
727
+ logger . raw ( `Short: webpack${ isCommandSpecified ? ` ${ commandName } ` : '' } ${ option . short } ${ value ? ` ${ value } ` : '' } ` ) ;
705
728
}
706
729
707
730
if ( option . description ) {
@@ -806,7 +829,7 @@ class WebpackCLI {
806
829
807
830
async resolveConfig ( options ) {
808
831
const loadConfig = async ( configPath ) => {
809
- const ext = extname ( configPath ) ;
832
+ const ext = path . extname ( configPath ) ;
810
833
const interpreted = Object . keys ( jsVariants ) . find ( ( variant ) => variant === ext ) ;
811
834
812
835
if ( interpreted ) {
@@ -906,7 +929,7 @@ class WebpackCLI {
906
929
if ( options . config && options . config . length > 0 ) {
907
930
const evaluatedConfigs = await Promise . all (
908
931
options . config . map ( async ( value ) => {
909
- const configPath = resolve ( value ) ;
932
+ const configPath = path . resolve ( value ) ;
910
933
911
934
if ( ! existsSync ( configPath ) ) {
912
935
logger . error ( `The specified config file doesn't exist in '${ configPath } '` ) ;
@@ -940,7 +963,7 @@ class WebpackCLI {
940
963
. map ( ( filename ) =>
941
964
// Since .cjs is not available on interpret side add it manually to default config extension list
942
965
[ ...Object . keys ( extensions ) , '.cjs' ] . map ( ( ext ) => ( {
943
- path : resolve ( filename + ext ) ,
966
+ path : path . resolve ( filename + ext ) ,
944
967
ext : ext ,
945
968
module : extensions [ ext ] ,
946
969
} ) ) ,
@@ -1373,6 +1396,7 @@ class WebpackCLI {
1373
1396
}
1374
1397
1375
1398
if ( options . json ) {
1399
+ const { stringifyStream : createJsonStringifyStream } = require ( '@discoveryjs/json-ext' ) ;
1376
1400
const handleWriteError = ( error ) => {
1377
1401
logger . error ( error ) ;
1378
1402
process . exit ( 2 ) ;
0 commit comments