@@ -5,37 +5,15 @@ const WEBPACK_PACKAGE = process.env.WEBPACK_PACKAGE || "webpack";
55const WEBPACK_DEV_SERVER_PACKAGE = process . env . WEBPACK_DEV_SERVER_PACKAGE || "webpack-dev-server" ;
66
77type Problem = NonNullable < ReturnType < typeof cli [ "processArguments" ] > > [ 0 ] ;
8- type PublicPath = WebpackDevServerOptions [ "output" ] [ "publicPath" ] ;
8+
99class ServeCommand {
1010 async apply ( cli : IWebpackCLI ) : Promise < void > {
1111 const loadDevServerOptions = ( ) => {
12- // TODO simplify this after drop webpack v4 and webpack-dev-server v3
1312 // eslint-disable-next-line @typescript-eslint/no-var-requires
1413 const devServer = require ( WEBPACK_DEV_SERVER_PACKAGE ) ;
15- const isNewDevServerCLIAPI = typeof devServer . schema !== "undefined" ;
1614
1715 // eslint-disable-next-line @typescript-eslint/no-explicit-any
18- let options : Record < string , any > = { } ;
19-
20- if ( isNewDevServerCLIAPI ) {
21- if ( cli . webpack . cli && typeof cli . webpack . cli . getArguments === "function" ) {
22- options = cli . webpack . cli . getArguments ( devServer . schema ) ;
23- } else {
24- options = devServer . cli . getArguments ( ) ;
25- }
26- } else {
27- options = require ( `${ WEBPACK_DEV_SERVER_PACKAGE } /bin/cli-flags` ) ;
28- }
29-
30- // Old options format
31- // { devServer: [{...}, {}...] }
32- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
33- // @ts -ignore
34- if ( options . devServer ) {
35- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
36- // @ts -ignore
37- return options . devServer ;
38- }
16+ const options : Record < string , any > = cli . webpack . cli . getArguments ( devServer . schema ) ;
3917
4018 // New options format
4119 // { flag1: {}, flag2: {} }
@@ -151,16 +129,7 @@ class ServeCommand {
151129 process . stdin . on ( "end" , ( ) => {
152130 Promise . all (
153131 servers . map ( ( server ) => {
154- if ( typeof server . stop === "function" ) {
155- return server . stop ( ) ;
156- }
157-
158- // TODO remove in the next major release
159- return new Promise < void > ( ( resolve ) => {
160- server . close ( ( ) => {
161- resolve ( ) ;
162- } ) ;
163- } ) ;
132+ return server . stop ( ) ;
164133 } ) ,
165134 ) . then ( ( ) => {
166135 process . exit ( 0 ) ;
@@ -171,13 +140,10 @@ class ServeCommand {
171140
172141 // eslint-disable-next-line @typescript-eslint/no-var-requires
173142 const DevServer = require ( WEBPACK_DEV_SERVER_PACKAGE ) ;
174- const isNewDevServerCLIAPI = typeof DevServer . schema !== "undefined" ;
175-
176- let devServerVersion ;
177143
178144 try {
179145 // eslint-disable-next-line @typescript-eslint/no-var-requires
180- devServerVersion = require ( `${ WEBPACK_DEV_SERVER_PACKAGE } /package.json` ) . version ;
146+ require ( `${ WEBPACK_DEV_SERVER_PACKAGE } /package.json` ) . version ;
181147 } catch ( err ) {
182148 cli . logger . error (
183149 `You need to install 'webpack-dev-server' for running 'webpack serve'.\n${ err } ` ,
@@ -191,142 +157,69 @@ class ServeCommand {
191157 ) ;
192158 const compilersForDevServer =
193159 possibleCompilers . length > 0 ? possibleCompilers : [ compilers [ 0 ] ] ;
194- const isDevServer4 = devServerVersion . startsWith ( "4" ) ;
195160 const usedPorts : number [ ] = [ ] ;
196161
197162 for ( const compilerForDevServer of compilersForDevServer ) {
198- let devServerOptions : WebpackDevServerOptions ;
163+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
164+ const args = devServerFlags . reduce ( ( accumulator : Record < string , any > , flag : any ) => {
165+ accumulator [ flag . name ] = flag ;
199166
200- if ( isNewDevServerCLIAPI ) {
167+ return accumulator ;
168+ } , { } ) ;
169+ const values = Object . keys ( devServerCLIOptions ) . reduce (
201170 // eslint-disable-next-line @typescript-eslint/no-explicit-any
202- const args = devServerFlags . reduce ( ( accumulator : Record < string , any > , flag : any ) => {
203- accumulator [ flag . name ] = flag ;
204-
205- return accumulator ;
206- } , { } ) ;
207- const values = Object . keys ( devServerCLIOptions ) . reduce (
208- // eslint-disable-next-line @typescript-eslint/no-explicit-any
209- ( accumulator : Record < string , any > , name : string ) => {
210- const kebabName = cli . toKebabCase ( name ) ;
211-
212- if ( args [ kebabName ] ) {
213- accumulator [ kebabName ] = options [ name ] ;
214- }
171+ ( accumulator : Record < string , any > , name : string ) => {
172+ const kebabName = cli . toKebabCase ( name ) ;
215173
216- return accumulator ;
217- } ,
218- { } ,
219- ) ;
220- const result = { ...( compilerForDevServer . options . devServer || { } ) } ;
221- const problems = (
222- cli . webpack . cli && typeof cli . webpack . cli . processArguments === "function"
223- ? cli . webpack . cli
224- : DevServer . cli
225- ) . processArguments ( args , result , values ) ;
226-
227- if ( problems ) {
228- const groupBy = ( xs : Problem [ ] , key : keyof Problem ) => {
229- return xs . reduce ( ( rv : { [ key : string ] : Problem [ ] } , x : Problem ) => {
230- ( rv [ x [ key ] ] = rv [ x [ key ] ] || [ ] ) . push ( x ) ;
231-
232- return rv ;
233- } , { } ) ;
234- } ;
235-
236- const problemsByPath = groupBy ( problems , "path" ) ;
237-
238- for ( const path in problemsByPath ) {
239- const problems = problemsByPath [ path ] ;
240-
241- problems . forEach ( ( problem : Problem ) => {
242- cli . logger . error (
243- `${ cli . capitalizeFirstLetter ( problem . type . replace ( / - / g, " " ) ) } ${
244- problem . value ? ` '${ problem . value } '` : ""
245- } for the '--${ problem . argument } ' option${
246- problem . index ? ` by index '${ problem . index } '` : ""
247- } `,
248- ) ;
249-
250- if ( problem . expected ) {
251- cli . logger . error ( `Expected: '${ problem . expected } '` ) ;
252- }
253- } ) ;
174+ if ( args [ kebabName ] ) {
175+ accumulator [ kebabName ] = options [ name ] ;
254176 }
255177
256- process . exit ( 2 ) ;
257- }
258-
259- devServerOptions = result as WebpackDevServerOptions ;
260- } else {
261- // TODO remove in the next major release
262- const mergeOptions = (
263- devServerOptions : Partial < WebpackDevServerOptions > ,
264- devServerCliOptions : Partial < WebpackDevServerOptions > ,
265- ) : WebpackDevServerOptions => {
266- // CLI options should take precedence over devServer options,
267- // and CLI options should have no default values included
268- const options = { ...devServerOptions , ...devServerCliOptions } ;
269-
270- if (
271- devServerOptions . client &&
272- devServerCliOptions . client &&
273- typeof devServerOptions . client === "object" &&
274- typeof devServerCliOptions . client === "object"
275- ) {
276- // the user could set some client options in their devServer config,
277- // then also specify client options on the CLI
278- options . client = {
279- ...devServerOptions . client ,
280- ...devServerCliOptions . client ,
281- } ;
282- }
283-
284- return options as WebpackDevServerOptions ;
178+ return accumulator ;
179+ } ,
180+ { } ,
181+ ) ;
182+ const result = { ...( compilerForDevServer . options . devServer || { } ) } ;
183+ const problems = (
184+ cli . webpack . cli && typeof cli . webpack . cli . processArguments === "function"
185+ ? cli . webpack . cli
186+ : DevServer . cli
187+ ) . processArguments ( args , result , values ) ;
188+
189+ if ( problems ) {
190+ const groupBy = ( xs : Problem [ ] , key : keyof Problem ) => {
191+ return xs . reduce ( ( rv : { [ key : string ] : Problem [ ] } , x : Problem ) => {
192+ ( rv [ x [ key ] ] = rv [ x [ key ] ] || [ ] ) . push ( x ) ;
193+
194+ return rv ;
195+ } , { } ) ;
285196 } ;
286197
287- devServerOptions = mergeOptions (
288- compilerForDevServer . options . devServer || { } ,
289- devServerCLIOptions ,
290- ) ;
291- }
292-
293- // TODO remove in the next major release
294- if ( ! isDevServer4 ) {
295- const getPublicPathOption = ( ) : PublicPath => {
296- const normalizePublicPath = ( publicPath : PublicPath ) : PublicPath =>
297- typeof publicPath === "undefined" || publicPath === "auto" ? "/" : publicPath ;
198+ const problemsByPath = groupBy ( problems , "path" ) ;
298199
299- if ( options . outputPublicPath ) {
300- return normalizePublicPath ( compilerForDevServer . options . output . publicPath ) ;
301- }
200+ for ( const path in problemsByPath ) {
201+ const problems = problemsByPath [ path ] ;
302202
303- if ( devServerOptions . publicPath ) {
304- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
305- // @ts -ignore
306- return normalizePublicPath ( devServerOptions . publicPath ) ;
307- }
203+ problems . forEach ( ( problem : Problem ) => {
204+ cli . logger . error (
205+ `${ cli . capitalizeFirstLetter ( problem . type . replace ( / - / g, " " ) ) } ${
206+ problem . value ? ` '${ problem . value } '` : ""
207+ } for the '--${ problem . argument } ' option${
208+ problem . index ? ` by index '${ problem . index } '` : ""
209+ } `,
210+ ) ;
308211
309- return normalizePublicPath ( compilerForDevServer . options . output . publicPath ) ;
310- } ;
311- const getStatsOption = ( ) : WebpackDevServerOptions [ "stats" ] => {
312- if ( options . stats ) {
313- return options . stats ;
314- }
315-
316- if ( devServerOptions . stats ) {
317- return devServerOptions . stats ;
318- }
319-
320- return compilerForDevServer . options . stats ;
321- } ;
212+ if ( problem . expected ) {
213+ cli . logger . error ( `Expected: '${ problem . expected } '` ) ;
214+ }
215+ } ) ;
216+ }
322217
323- devServerOptions . host = devServerOptions . host || "localhost" ;
324- devServerOptions . port =
325- typeof devServerOptions . port !== "undefined" ? devServerOptions . port : 8080 ;
326- devServerOptions . stats = getStatsOption ( ) ;
327- devServerOptions . publicPath = getPublicPathOption ( ) ;
218+ process . exit ( 2 ) ;
328219 }
329220
221+ const devServerOptions : WebpackDevServerOptions = result as WebpackDevServerOptions ;
222+
330223 if ( devServerOptions . port ) {
331224 const portNumber = Number ( devServerOptions . port ) ;
332225
@@ -340,25 +233,9 @@ class ServeCommand {
340233 }
341234
342235 try {
343- let server ;
236+ const server = new DevServer ( devServerOptions , compiler ) ;
344237
345- // TODO: remove after dropping webpack-dev-server@v3
346- if ( isDevServer4 ) {
347- server = new DevServer ( devServerOptions , compiler ) ;
348- } else {
349- server = new DevServer ( compiler , devServerOptions ) ;
350- }
351-
352- if ( typeof server . start === "function" ) {
353- await server . start ( ) ;
354- } else {
355- // TODO remove in the next major release
356- server . listen ( devServerOptions . port , devServerOptions . host , ( error : Error ) : void => {
357- if ( error ) {
358- throw error ;
359- }
360- } ) ;
361- }
238+ await server . start ( ) ;
362239
363240 servers . push ( server ) ;
364241 } catch ( error ) {
0 commit comments