1- const path = require ( 'path' ) ;
21const { program } = require ( 'commander' ) ;
32const getPkg = require ( './utils/package-exists' ) ;
43const webpack = getPkg ( 'webpack' ) ? require ( 'webpack' ) : undefined ;
4+ const path = require ( 'path' ) ;
55const { merge } = require ( 'webpack-merge' ) ;
66const { extensions, jsVariants } = require ( 'interpret' ) ;
77const rechoir = require ( 'rechoir' ) ;
88const { createWriteStream, existsSync } = require ( 'fs' ) ;
99const { distance } = require ( 'fastest-levenshtein' ) ;
1010const { options : coloretteOptions , yellow, cyan, green, bold } = require ( 'colorette' ) ;
11- const { stringifyStream : createJsonStringifyStream } = require ( '@discoveryjs/json-ext' ) ;
1211
1312const logger = require ( './utils/logger' ) ;
1413const { cli, flags } = require ( './utils/cli-flags' ) ;
1514const CLIPlugin = require ( './plugins/CLIPlugin' ) ;
1615const promptInstallation = require ( './utils/prompt-installation' ) ;
17-
1816const toKebabCase = require ( './utils/to-kebab-case' ) ;
1917
20- const { resolve, extname } = path ;
21-
2218class WebpackCLI {
2319 constructor ( ) {
24- this . logger = logger ;
2520 // Initialize program
2621 this . program = program ;
2722 this . program . name ( 'webpack' ) ;
2823 this . program . storeOptionsAsProperties ( false ) ;
24+ this . webpack = webpack ;
25+ this . logger = logger ;
2926 this . utils = { toKebabCase, getPkg, promptInstallation } ;
3027 }
3128
@@ -234,6 +231,12 @@ class WebpackCLI {
234231 description : 'Run webpack (default command, can be omitted).' ,
235232 usage : '[options]' ,
236233 } ;
234+ const watchCommandOptions = {
235+ name : 'watch' ,
236+ alias : 'w' ,
237+ description : 'Run webpack and watch for files changes.' ,
238+ usage : '[options]' ,
239+ } ;
237240 const versionCommandOptions = {
238241 name : 'version [commands...]' ,
239242 alias : 'v' ,
@@ -283,7 +286,13 @@ class WebpackCLI {
283286 } ,
284287 ] ;
285288
286- const knownCommands = [ buildCommandOptions , versionCommandOptions , helpCommandOptions , ...externalBuiltInCommandsInfo ] ;
289+ const knownCommands = [
290+ buildCommandOptions ,
291+ watchCommandOptions ,
292+ versionCommandOptions ,
293+ helpCommandOptions ,
294+ ...externalBuiltInCommandsInfo ,
295+ ] ;
287296 const getCommandName = ( name ) => name . split ( ' ' ) [ 0 ] ;
288297 const isKnownCommand = ( name ) =>
289298 knownCommands . find (
@@ -294,6 +303,9 @@ class WebpackCLI {
294303 const isBuildCommand = ( name ) =>
295304 getCommandName ( buildCommandOptions . name ) === name ||
296305 ( 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 ) ;
297309 const isHelpCommand = ( name ) =>
298310 getCommandName ( helpCommandOptions . name ) === name ||
299311 ( Array . isArray ( helpCommandOptions . alias ) ? helpCommandOptions . alias . includes ( name ) : helpCommandOptions . alias === name ) ;
@@ -338,21 +350,40 @@ class WebpackCLI {
338350 return { commandName : isDefault ? buildCommandOptions . name : commandName , options, isDefault } ;
339351 } ;
340352 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 ) ;
344355
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 ( ) ;
347362
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 ) ;
353365
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+ ) ;
356387 } else if ( isHelpCommand ( commandName ) ) {
357388 // Stub for the `help` command
358389 this . makeCommand ( helpCommandOptions , [ ] , ( ) => { } ) ;
@@ -492,9 +523,9 @@ class WebpackCLI {
492523 // Make `-v, --version` options
493524 // Make `version|v [commands...]` command
494525 const outputVersion = async ( options ) => {
495- // Filter `bundle`, `version` and `help` commands
526+ // Filter `bundle`, `watch`, ` version` and `help` commands
496527 const possibleCommandNames = options . filter (
497- ( option ) => ! isBuildCommand ( option ) && ! isVersionCommand ( option ) && ! isHelpCommand ( option ) ,
528+ ( option ) => ! isBuildCommand ( option ) && ! isWatchCommand ( option ) && ! isVersionCommand ( option ) && ! isHelpCommand ( option ) ,
498529 ) ;
499530
500531 possibleCommandNames . forEach ( ( possibleCommandName ) => {
@@ -616,7 +647,7 @@ class WebpackCLI {
616647 . replace ( buildCommandOptions . description , 'The build tool for modern web applications.' )
617648 . replace (
618649 / 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] ' ,
620651 ) ;
621652
622653 logger . raw ( helpInformation ) ;
@@ -643,25 +674,21 @@ class WebpackCLI {
643674 let helpInformation = command . helpInformation ( ) . trimRight ( ) ;
644675
645676 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' ) ;
652678 }
653679
654680 logger . raw ( helpInformation ) ;
655681
656682 outputGlobalOptions ( ) ;
657683 } else if ( isHelpCommandSyntax ) {
658- let commandName ;
684+ let isCommandSpecified = false ;
685+ let commandName = buildCommandOptions . name ;
659686 let optionName ;
660687
661688 if ( options . length === 1 ) {
662- commandName = buildCommandOptions . name ;
663689 optionName = options [ 0 ] ;
664690 } else if ( options . length === 2 ) {
691+ isCommandSpecified = true ;
665692 commandName = options [ 0 ] ;
666693 optionName = options [ 1 ] ;
667694
@@ -694,14 +721,10 @@ class WebpackCLI {
694721 option . flags . replace ( / ^ .+ [ [ < ] / , '' ) . replace ( / ( \. \. \. ) ? [ \] > ] .* $ / , '' ) + ( option . variadic === true ? '...' : '' ) ;
695722 const value = option . required ? '<' + nameOutput + '>' : option . optional ? '[' + nameOutput + ']' : '' ;
696723
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 } ` : '' } ` ) ;
700725
701726 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 } ` : '' } ` ) ;
705728 }
706729
707730 if ( option . description ) {
@@ -806,7 +829,7 @@ class WebpackCLI {
806829
807830 async resolveConfig ( options ) {
808831 const loadConfig = async ( configPath ) => {
809- const ext = extname ( configPath ) ;
832+ const ext = path . extname ( configPath ) ;
810833 const interpreted = Object . keys ( jsVariants ) . find ( ( variant ) => variant === ext ) ;
811834
812835 if ( interpreted ) {
@@ -906,7 +929,7 @@ class WebpackCLI {
906929 if ( options . config && options . config . length > 0 ) {
907930 const evaluatedConfigs = await Promise . all (
908931 options . config . map ( async ( value ) => {
909- const configPath = resolve ( value ) ;
932+ const configPath = path . resolve ( value ) ;
910933
911934 if ( ! existsSync ( configPath ) ) {
912935 logger . error ( `The specified config file doesn't exist in '${ configPath } '` ) ;
@@ -940,7 +963,7 @@ class WebpackCLI {
940963 . map ( ( filename ) =>
941964 // Since .cjs is not available on interpret side add it manually to default config extension list
942965 [ ...Object . keys ( extensions ) , '.cjs' ] . map ( ( ext ) => ( {
943- path : resolve ( filename + ext ) ,
966+ path : path . resolve ( filename + ext ) ,
944967 ext : ext ,
945968 module : extensions [ ext ] ,
946969 } ) ) ,
@@ -1373,6 +1396,7 @@ class WebpackCLI {
13731396 }
13741397
13751398 if ( options . json ) {
1399+ const { stringifyStream : createJsonStringifyStream } = require ( '@discoveryjs/json-ext' ) ;
13761400 const handleWriteError = ( error ) => {
13771401 logger . error ( error ) ;
13781402 process . exit ( 2 ) ;
0 commit comments