@@ -2,134 +2,29 @@ const { packageExists } = require('./package-exists');
22const webpack = packageExists ( 'webpack' ) ? require ( 'webpack' ) : undefined ;
33const logger = require ( './logger' ) ;
44const { writeFileSync } = require ( 'fs' ) ;
5- const bailAndWatchWarning = require ( './warnings/bailAndWatchWarning' ) ;
6-
7- const assignWatchHooks = ( compiler ) => {
8- compiler . hooks . watchRun . tap ( 'watchInfo' , ( compilation ) => {
9- const compilationName = compilation . name || '' ;
10- logger . raw ( `\nCompilation ${ compilationName } starting…\n` ) ;
11- } ) ;
12- compiler . hooks . done . tap ( 'watchInfo' , ( compilation ) => {
13- const compilationName = compilation . name || '' ;
14- logger . raw ( `\nCompilation ${ compilationName } finished\n` ) ;
15- } ) ;
16- } ;
17-
18- const watchInfo = ( compiler ) => {
19- if ( compiler . compilers ) {
20- compiler . compilers . map ( ( comp ) => {
21- assignWatchHooks ( comp ) ;
22- } ) ;
23- } else {
24- assignWatchHooks ( compiler ) ;
25- }
26- } ;
275
286class Compiler {
297 constructor ( ) {
308 this . compilerOptions = { } ;
319 }
32- setUpHookForCompilation ( compilation , outputOptions , options ) {
33- const { ProgressPlugin } = webpack ;
34- let progressPluginExists ;
35- if ( options . plugins ) {
36- progressPluginExists = options . plugins . find ( ( e ) => e instanceof ProgressPlugin ) ;
37- }
38-
39- compilation . hooks . beforeRun . tap ( 'webpackProgress' , ( ) => {
40- if ( outputOptions . progress ) {
41- if ( ! progressPluginExists ) {
42- new ProgressPlugin ( ) . apply ( compilation ) ;
43- } else {
44- if ( ! progressPluginExists . handler ) {
45- options . plugins = options . plugins . filter ( ( e ) => e !== progressPluginExists ) ;
46- Object . keys ( progressPluginExists ) . map ( ( opt ) => {
47- ProgressPlugin . defaultOptions [ opt ] = progressPluginExists [ opt ] ;
48- } ) ;
49- new ProgressPlugin ( ) . apply ( compilation ) ;
50- } else {
51- progressPluginExists . apply ( compilation ) ;
52- }
53- }
54- }
55- } ) ;
56- }
57-
58- compilerCallback ( error , stats , lastHash , options , outputOptions ) {
59- if ( error ) {
60- lastHash = null ;
61- logger . error ( error ) ;
62- process . exit ( 1 ) ;
63- }
64-
65- if ( ! outputOptions . watch && stats . hasErrors ( ) ) {
66- process . exitCode = 1 ;
67- }
68-
69- if ( stats . hash !== lastHash ) {
70- lastHash = stats . hash ;
71-
72- if ( outputOptions . json === true ) {
73- process . stdout . write ( JSON . stringify ( stats . toJson ( outputOptions ) , null , 2 ) + '\n' ) ;
74- } else if ( typeof outputOptions . json === 'string' ) {
75- const JSONStats = JSON . stringify ( stats . toJson ( outputOptions ) , null , 2 ) ;
76-
77- try {
78- writeFileSync ( outputOptions . json , JSONStats ) ;
79- logger . success ( `stats are successfully stored as json to ${ outputOptions . json } ` ) ;
80- } catch ( err ) {
81- logger . error ( err ) ;
82- }
83- } else {
84- logger . raw ( `${ stats . toString ( this . compilerOptions . stats ) } \n` ) ;
85- }
86-
87- if ( outputOptions . watch ) {
88- logger . info ( 'watching files for updates...' ) ;
89- }
90- }
91- }
92-
93- async invokeCompilerInstance ( lastHash , options , outputOptions ) {
94- // eslint-disable-next-line no-async-promise-executor
95- return new Promise ( async ( resolve ) => {
96- await this . compiler . run ( ( err , stats ) => {
97- if ( this . compiler . close ) {
98- this . compiler . close ( ( ) => {
99- this . compilerCallback ( err , stats , lastHash , options , outputOptions ) ;
100-
101- resolve ( ) ;
102- } ) ;
103- } else {
104- this . compilerCallback ( err , stats , lastHash , options , outputOptions ) ;
105-
106- resolve ( ) ;
107- }
108- } ) ;
109- } ) ;
110- }
111-
112- async invokeWatchInstance ( lastHash , options , outputOptions , watchOptions ) {
113- return this . compiler . watch ( watchOptions , ( err , stats ) => {
114- this . compilerCallback ( err , stats , lastHash , options , outputOptions ) ;
115- } ) ;
116- }
11710
11811 async createCompiler ( options ) {
11912 try {
12013 this . compiler = await webpack ( options ) ;
12114 this . compilerOptions = options ;
122- } catch ( err ) {
15+ } catch ( error ) {
12316 // https://github.com/webpack/webpack/blob/master/lib/index.js#L267
12417 // https://github.com/webpack/webpack/blob/v4.44.2/lib/webpack.js#L90
12518 const ValidationError = webpack . ValidationError ? webpack . ValidationError : webpack . WebpackOptionsValidationError ;
19+
12620 // In case of schema errors print and exit process
12721 // For webpack@4 and webpack@5
128- if ( err instanceof ValidationError ) {
129- logger . error ( `\n ${ err . message } ` ) ;
22+ if ( error instanceof ValidationError ) {
23+ logger . error ( error . message ) ;
13024 } else {
131- logger . error ( `\n ${ err } ` ) ;
25+ logger . error ( error ) ;
13226 }
27+
13328 process . exit ( 2 ) ;
13429 }
13530 }
@@ -140,39 +35,115 @@ class Compiler {
14035
14136 async webpackInstance ( opts ) {
14237 const { outputOptions, options } = opts ;
143- const lastHash = null ;
144-
145- const { ProgressPlugin } = webpack ;
146- if ( options . plugins ) {
147- options . plugins = options . plugins . filter ( ( e ) => e instanceof ProgressPlugin ) ;
148- }
14938
15039 if ( outputOptions . interactive ) {
15140 const interactive = require ( './interactive' ) ;
41+
15242 return interactive ( options , outputOptions ) ;
15343 }
154- if ( this . compiler . compilers ) {
155- this . compiler . compilers . forEach ( ( comp , idx ) => {
156- bailAndWatchWarning ( comp ) ; //warn the user if bail and watch both are used together
157- this . setUpHookForCompilation ( comp , outputOptions , options [ idx ] ) ;
44+
45+ const compilers = this . compiler . compilers ? this . compiler . compilers : [ this . compiler ] ;
46+ const isWatchMode = Boolean ( compilers . find ( ( compiler ) => compiler . options . watch ) ) ;
47+ const isRawOutput = typeof outputOptions . json === 'undefined' ;
48+
49+ if ( isRawOutput ) {
50+ for ( const compiler of compilers ) {
51+ if ( outputOptions . progress ) {
52+ const { ProgressPlugin } = webpack ;
53+
54+ let progressPluginExists ;
55+
56+ if ( compiler . options . plugins ) {
57+ progressPluginExists = Boolean ( compiler . options . plugins . find ( ( e ) => e instanceof ProgressPlugin ) ) ;
58+ }
59+
60+ if ( ! progressPluginExists ) {
61+ new ProgressPlugin ( ) . apply ( compiler ) ;
62+ }
63+ }
64+ }
65+
66+ this . compiler . hooks . watchRun . tap ( 'watchInfo' , ( compilation ) => {
67+ if ( compilation . options . bail && isWatchMode ) {
68+ logger . warn ( 'You are using "bail" with "watch". "bail" will still exit webpack when the first error is found.' ) ;
69+ }
70+
71+ logger . success ( `Compilation${ compilation . name ? `${ compilation . name } ` : '' } starting...` ) ;
72+ } ) ;
73+ this . compiler . hooks . done . tap ( 'watchInfo' , ( compilation ) => {
74+ logger . success ( `Compilation${ compilation . name ? `${ compilation . name } ` : '' } finished` ) ;
15875 } ) ;
159- } else {
160- bailAndWatchWarning ( this . compiler ) ;
161- this . setUpHookForCompilation ( this . compiler , outputOptions , options ) ;
16276 }
16377
164- if ( outputOptions . watch ) {
165- const watchOptions = outputOptions . watchOptions || { } ;
78+ const callback = ( error , stats ) => {
79+ if ( error ) {
80+ logger . error ( error ) ;
81+ process . exit ( 1 ) ;
82+ }
83+
84+ if ( stats . hasErrors ( ) ) {
85+ process . exitCode = 1 ;
86+ }
87+
88+ const foundStats = this . compiler . compilers
89+ ? { children : this . compiler . compilers . map ( ( compiler ) => compiler . options . stats ) }
90+ : this . compiler . options . stats ;
91+
92+ if ( outputOptions . json === true ) {
93+ process . stdout . write ( JSON . stringify ( stats . toJson ( foundStats ) , null , 2 ) + '\n' ) ;
94+ } else if ( typeof outputOptions . json === 'string' ) {
95+ const JSONStats = JSON . stringify ( stats . toJson ( foundStats ) , null , 2 ) ;
96+
97+ try {
98+ writeFileSync ( outputOptions . json , JSONStats ) ;
99+ logger . success ( `stats are successfully stored as json to ${ outputOptions . json } ` ) ;
100+ } catch ( error ) {
101+ logger . error ( error ) ;
102+
103+ process . exit ( 2 ) ;
104+ }
105+ } else {
106+ logger . raw ( `${ stats . toString ( foundStats ) } ` ) ;
107+ }
108+
109+ if ( isWatchMode ) {
110+ logger . success ( 'watching files for updates...' ) ;
111+ }
112+ } ;
113+
114+ if ( isWatchMode ) {
115+ const watchOptions = ( this . compiler . options && this . compiler . options . watchOptions ) || { } ;
116+
166117 if ( watchOptions . stdin ) {
167118 process . stdin . on ( 'end' , function ( ) {
168119 process . exit ( ) ;
169120 } ) ;
170121 process . stdin . resume ( ) ;
171122 }
172- watchInfo ( this . compiler ) ;
173- await this . invokeWatchInstance ( lastHash , options , outputOptions , watchOptions ) ;
123+
124+ return new Promise ( ( resolve ) => {
125+ this . compiler . watch ( watchOptions , ( error , stats ) => {
126+ callback ( error , stats ) ;
127+
128+ resolve ( ) ;
129+ } ) ;
130+ } ) ;
174131 } else {
175- return await this . invokeCompilerInstance ( lastHash , options , outputOptions ) ;
132+ return new Promise ( ( resolve ) => {
133+ this . compiler . run ( ( error , stats ) => {
134+ if ( this . compiler . close ) {
135+ this . compiler . close ( ( ) => {
136+ callback ( error , stats ) ;
137+
138+ resolve ( ) ;
139+ } ) ;
140+ } else {
141+ callback ( error , stats ) ;
142+
143+ resolve ( ) ;
144+ }
145+ } ) ;
146+ } ) ;
176147 }
177148 }
178149}
0 commit comments