File tree Expand file tree Collapse file tree
test/serve/error-handling Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -2296,7 +2296,9 @@ class WebpackCLI {
22962296 // needed for `webpack-dev-server@5` typings, which lack the plugin constructor
22972297 const DevServerPlugin = DevServer as unknown as new ( options : DevServerConfiguration ) => {
22982298 apply ( compiler : Compiler | MultiCompiler ) : void ;
2299+ listen ( ) : Promise < void > ;
22992300 } ;
2301+ const plugins : InstanceType < typeof DevServerPlugin > [ ] = [ ] ;
23002302
23012303 const compiler = await this . createCompiler (
23022304 webpackCLIOptions ,
@@ -2361,6 +2363,8 @@ class WebpackCLI {
23612363 setupExitSignals : false ,
23622364 } ) ;
23632365
2366+ plugins . push ( plugin ) ;
2367+
23642368 if ( isDevServerPerCompiler ) {
23652369 configuration . plugins = [ ...( configuration . plugins || [ ] ) , plugin ] ;
23662370 } else {
@@ -2406,6 +2410,25 @@ class WebpackCLI {
24062410 return ;
24072411 }
24082412
2413+ // TODO remove it when webpack-dev-server reports listen failures to the compiler
2414+ // A dev server only logs a failure to listen, e.g. a port already in use, and the
2415+ // CLI would keep watching without it, so exit like dev servers without plugin
2416+ // support do
2417+ for ( const plugin of plugins ) {
2418+ const { listen } = plugin ;
2419+
2420+ plugin . listen = ( ) =>
2421+ listen . call ( plugin ) . catch ( ( error ) => {
2422+ process . exitCode = 2 ;
2423+
2424+ compiler . close ( ( ) => {
2425+ process . exit ( ) ;
2426+ } ) ;
2427+
2428+ throw error ;
2429+ } ) ;
2430+ }
2431+
24092432 // Closing the compiler stops dev servers, failures keep the exit code
24102433 this . #setupGracefulShutdown( compiler , true ) ;
24112434
Original file line number Diff line number Diff line change 33/* eslint-disable jest/require-top-level-describe -- Version-gated describe */
44
55const fs = require ( "node:fs" ) ;
6+ const net = require ( "node:net" ) ;
67const os = require ( "node:os" ) ;
78const path = require ( "node:path" ) ;
89const [ devServerVersion ] = require ( "webpack-dev-server/package.json" ) . version ;
@@ -163,6 +164,33 @@ describeDevServer6("serve error handling", () => {
163164 expect ( stdout ) . toBeFalsy ( ) ;
164165 } ) ;
165166
167+ test ( "should log the error and exit when the port is already in use" , async ( ) => {
168+ const server = net . createServer ( ) ;
169+
170+ await new Promise ( ( resolve ) => {
171+ server . listen ( port , "127.0.0.1" , resolve ) ;
172+ } ) ;
173+
174+ try {
175+ const { exitCode, stderr } = await run ( __dirname , [
176+ "serve" ,
177+ "--config" ,
178+ "recover.config.js" ,
179+ "--env" ,
180+ `entry=${ path . resolve ( __dirname , "src/index.js" ) } ` ,
181+ "--host" ,
182+ "127.0.0.1" ,
183+ "--port" ,
184+ port ,
185+ ] ) ;
186+
187+ expect ( exitCode ) . toBe ( 2 ) ;
188+ expect ( stderr ) . toContain ( "EADDRINUSE" ) ;
189+ } finally {
190+ server . close ( ) ;
191+ }
192+ } ) ;
193+
166194 test ( "should log the validation error and exit when a middleware option is invalid" , async ( ) => {
167195 const { exitCode, stderr, stdout } = await run ( __dirname , [
168196 "serve" ,
You can’t perform that action at this time.
0 commit comments