diff --git a/bin/webpack-dev-server.js b/bin/webpack-dev-server.js index 224a69d978..a575fb17df 100755 --- a/bin/webpack-dev-server.js +++ b/bin/webpack-dev-server.js @@ -113,19 +113,13 @@ function startDevServer(config, options) { throw err; } - if (options.socket) { - server.listen(options.socket, options.host, (err) => { - if (err) { - throw err; - } - }); - } else { - server.listen(options.port, options.host, (err) => { - if (err) { - throw err; - } - }); - } + // options.socket does not have a default value, so it will only be set + // if the user sets it explicitly + server.listen(options.socket || options.port, options.host, (err) => { + if (err) { + throw err; + } + }); } processOptions(config, argv, (config, options) => { diff --git a/lib/Server.js b/lib/Server.js index 1a8f83ea60..1d59bcbca3 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -740,12 +740,12 @@ class Server { // between setupCallback and userCallback should be any other needed handling, // specifically so that things are done in the right order to prevent - // backwards compatability issues + // backwards compatibility issues let userCallbackCalled = false; - const userCallback = (err) => { + const userCallback = async (err) => { if (fn && !userCallbackCalled) { userCallbackCalled = true; - fn.call(this.listeningApp, err); + await fn.call(this.listeningApp, err); } }; @@ -755,9 +755,9 @@ class Server { } }; - const fullCallback = (err) => { + const fullCallback = async (err) => { setupCallback(); - userCallback(err); + await userCallback(err); onListeningCallback(); }; diff --git a/test/server/Server.test.js b/test/server/Server.test.js index d54712a087..7fa99b84ce 100644 --- a/test/server/Server.test.js +++ b/test/server/Server.test.js @@ -7,6 +7,7 @@ const { noop } = require('webpack-dev-middleware/lib/util'); const Server = require('../../lib/Server'); const config = require('../fixtures/simple-config/webpack.config'); const port = require('../ports-map').Server; +const timer = require('../helpers/timer'); jest.mock('sockjs/lib/transport'); @@ -178,4 +179,28 @@ describe('Server', () => { }); }); }); + + describe('server.listen', () => { + it('should complete async callback before calling onListening', (done) => { + const callOrder = []; + const compiler = webpack(config); + const server = new Server(compiler, { + onListening: () => { + callOrder.push('onListening'); + }, + ...baseDevConfig, + }); + server.listen(port, '0.0.0.0', async () => { + await timer(1000); + callOrder.push('user callback'); + }); + + // we need a timeout because even if the server is done listening, + // the compiler might still be compiling + setTimeout(() => { + expect(callOrder).toMatchSnapshot(); + server.close(done); + }, 5000); + }); + }); }); diff --git a/test/server/__snapshots__/Server.test.js.snap b/test/server/__snapshots__/Server.test.js.snap index b39da65eb6..59ec7f1b8f 100644 --- a/test/server/__snapshots__/Server.test.js.snap +++ b/test/server/__snapshots__/Server.test.js.snap @@ -59,3 +59,10 @@ Array [ }, ] `; + +exports[`Server server.listen should complete async callback before calling onListening 1`] = ` +Array [ + "user callback", + "onListening", +] +`;