diff --git a/bin/utils.js b/bin/utils.js index 21873a1509..78b70f2a79 100644 --- a/bin/utils.js +++ b/bin/utils.js @@ -7,26 +7,6 @@ array-bracket-spacing, space-before-function-paren */ -const open = require('opn'); - -const colors = { - info (useColor, msg) { - if (useColor) { - // Make text blue and bold, so it *pops* - return `\u001b[1m\u001b[34m${msg}\u001b[39m\u001b[22m`; - } - - return msg; - }, - error (useColor, msg) { - if (useColor) { - // Make text red and bold, so it *pops* - return `\u001b[1m\u001b[31m${msg}\u001b[39m\u001b[22m`; - } - - return msg; - } -}; // eslint-disable-next-line const defaultTo = (value, def) => { @@ -38,77 +18,4 @@ function version () { `webpack ${require('webpack/package.json').version}`; } -function status (uri, options, log, useColor) { - const contentBase = Array.isArray(options.contentBase) - ? options.contentBase.join(', ') - : options.contentBase; - - if (options.socket) { - log.info(`Listening to socket at ${colors.info(useColor, options.socket)}`); - } else { - log.info(`Project is running at ${colors.info(useColor, uri)}`); - } - - log.info( - `webpack output is served from ${colors.info(useColor, options.publicPath)}` - ); - - if (contentBase) { - log.info( - `Content not from webpack is served from ${colors.info(useColor, contentBase)}` - ); - } - - if (options.historyApiFallback) { - log.info( - `404s will fallback to ${colors.info(useColor, options.historyApiFallback.index || '/index.html')}` - ); - } - - if (options.bonjour) { - log.info( - 'Broadcasting "http" with subtype of "webpack" via ZeroConf DNS (Bonjour)' - ); - } - - if (options.open) { - let openOptions = {}; - let openMessage = 'Unable to open browser'; - - if (typeof options.open === 'string') { - openOptions = { app: options.open }; - openMessage += `: ${options.open}`; - } - - open(uri + (options.openPage || ''), openOptions).catch(() => { - log.warn( - `${openMessage}. If you are running in a headless environment, please do not use the --open flag` - ); - }); - } -} - -function bonjour (options) { - const bonjour = require('bonjour')(); - - bonjour.publish({ - name: 'Webpack Dev Server', - port: options.port, - type: 'http', - subtypes: [ 'webpack' ] - }); - - process.on('exit', () => { - bonjour.unpublishAll(() => { - bonjour.destroy(); - }); - }); -} - -module.exports = { - status, - colors, - version, - bonjour, - defaultTo -}; +module.exports = { version, defaultTo }; diff --git a/bin/webpack-dev-server.js b/bin/webpack-dev-server.js index a58a86564a..cde8aa58ab 100755 --- a/bin/webpack-dev-server.js +++ b/bin/webpack-dev-server.js @@ -16,7 +16,6 @@ const debug = require('debug')('webpack-dev-server'); const fs = require('fs'); -const net = require('net'); const path = require('path'); const portfinder = require('portfinder'); @@ -27,19 +26,13 @@ const webpack = require('webpack'); const options = require('./options'); -const { - colors, - status, - version, - bonjour, - defaultTo -} = require('./utils'); +const { version, defaultTo } = require('./utils'); const Server = require('../lib/Server'); const addEntries = require('../lib/utils/addEntries'); -const createDomain = require('../lib/utils/createDomain'); const createLogger = require('../lib/utils/createLogger'); +const colors = require('../lib/utils/colors'); let server; @@ -325,8 +318,6 @@ function startDevServer(config, options) { }).apply(compiler); } - const suffix = (options.inline !== false || options.lazy === true ? '/' : '/webpack-dev-server/'); - try { server = new Server(compiler, options, log); } catch (err) { @@ -338,63 +329,6 @@ function startDevServer(config, options) { throw err; } - - if (options.socket) { - server.listeningApp.on('error', (e) => { - if (e.code === 'EADDRINUSE') { - const clientSocket = new net.Socket(); - - clientSocket.on('error', (err) => { - if (err.code === 'ECONNREFUSED') { - // No other server listening on this socket so it can be safely removed - fs.unlinkSync(options.socket); - - server.listen(options.socket, options.host, (error) => { - if (error) { - throw error; - } - }); - } - }); - - clientSocket.connect({ path: options.socket }, () => { - throw new Error('This socket is already used'); - }); - } - }); - - server.listen(options.socket, options.host, (err) => { - if (err) { - throw err; - } - // chmod 666 (rw rw rw) - const READ_WRITE = 438; - - fs.chmod(options.socket, READ_WRITE, (err) => { - if (err) { - throw err; - } - - const uri = createDomain(options, server.listeningApp) + suffix; - - status(uri, options, log, argv.color); - }); - }); - } else { - server.listen(options.port, options.host, (err) => { - if (err) { - throw err; - } - - if (options.bonjour) { - bonjour(options); - } - - const uri = createDomain(options, server.listeningApp) + suffix; - - status(uri, options, log, argv.color); - }); - } } processOptions(config); diff --git a/lib/Server.js b/lib/Server.js index a5d17bf3b6..ebf1bf8aad 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -11,6 +11,7 @@ */ const fs = require('fs'); const path = require('path'); +const net = require('net'); const ip = require('ip'); const tls = require('tls'); @@ -37,8 +38,12 @@ const historyApiFallback = require('connect-history-api-fallback'); const webpack = require('webpack'); const webpackDevMiddleware = require('webpack-dev-middleware'); -const createLogger = require('./utils/createLogger'); +const createBonjour = require('./utils/createBonjour'); const createCertificate = require('./utils/createCertificate'); +const createDomain = require('../lib/utils/createDomain'); +const createLogger = require('./utils/createLogger'); +const logStatus = require('./utils/logStatus'); +const open = require('./utils/open'); const validateOptions = require('schema-utils'); const schema = require('./options.json'); @@ -640,6 +645,73 @@ function Server (compiler, options = {}, _log) { websocketProxies.forEach(function (wsProxy) { this.listeningApp.on('upgrade', wsProxy.upgrade); }, this); + + const suffix = (options.inline !== false || options.lazy === true ? '/' : '/webpack-dev-server/'); + + if (options.socket) { + this.listeningApp.on('error', (e) => { + if (e.code === 'EADDRINUSE') { + const clientSocket = new net.Socket(); + + clientSocket.on('error', (err) => { + if (err.code === 'ECONNREFUSED') { + // No other server listening on this socket so it can be safely removed + fs.unlinkSync(options.socket); + + this.listen(options.socket, options.host, (error) => { + if (error) { + throw error; + } + }); + } + }); + + clientSocket.connect({ path: options.socket }, () => { + throw new Error('This socket is already used'); + }); + } + }); + + this.listen(options.socket, options.host, (err) => { + if (err) { + throw err; + } + // chmod 666 (rw rw rw) + const READ_WRITE = 438; + + fs.chmod(options.socket, READ_WRITE, (err) => { + if (err) { + throw err; + } + + const uri = createDomain(options, this.listeningApp) + suffix; + + logStatus(uri, options, this.log, options.stats.colors); + + if (options.open) { + open(uri, options, this.log); + } + }); + }); + } else { + this.listen(options.port, options.host, (err) => { + if (err) { + throw err; + } + + if (options.bonjour) { + createBonjour(options); + } + + const uri = createDomain(options, this.listeningApp) + suffix; + + logStatus(uri, options, this.log, options.stats.colors); + + if (options.open) { + open(uri, options, this.log); + } + }); + } } Server.prototype.use = function () { diff --git a/lib/utils/colors.js b/lib/utils/colors.js new file mode 100644 index 0000000000..d312053b27 --- /dev/null +++ b/lib/utils/colors.js @@ -0,0 +1,22 @@ +'use strict'; + +const colors = { + info(useColor, msg) { + if (useColor) { + // Make text blue and bold, so it *pops* + return `\u001b[1m\u001b[34m${msg}\u001b[39m\u001b[22m`; + } + + return msg; + }, + error(useColor, msg) { + if (useColor) { + // Make text red and bold, so it *pops* + return `\u001b[1m\u001b[31m${msg}\u001b[39m\u001b[22m`; + } + + return msg; + } +}; + +module.exports = colors; diff --git a/lib/utils/createBonjour.js b/lib/utils/createBonjour.js new file mode 100644 index 0000000000..9a4184f828 --- /dev/null +++ b/lib/utils/createBonjour.js @@ -0,0 +1,24 @@ +'use strict'; + +/* eslint-disable + global-require, +*/ + +function createBonjour(options) { + const bonjour = require('bonjour')(); + + bonjour.publish({ + name: 'Webpack Dev Server', + port: options.port, + type: 'http', + subtypes: ['webpack'] + }); + + process.on('exit', () => { + bonjour.unpublishAll(() => { + bonjour.destroy(); + }); + }); +} + +module.exports = createBonjour; diff --git a/lib/utils/logStatus.js b/lib/utils/logStatus.js new file mode 100644 index 0000000000..dc3e199f49 --- /dev/null +++ b/lib/utils/logStatus.js @@ -0,0 +1,43 @@ +'use strict'; + +/* eslint-disable + multiline-ternary +*/ + +const colors = require('./colors'); + +function logStatus(uri, options, log, useColor) { + const contentBase = Array.isArray(options.contentBase) + ? options.contentBase.join(', ') + : options.contentBase; + + if (options.socket) { + log.info(`Listening to socket at ${colors.info(useColor, options.socket)}`); + } else { + log.info(`Project is running at ${colors.info(useColor, uri)}`); + } + + log.info( + `webpack output is served from ${colors.info(useColor, options.publicPath)}` + ); + + if (contentBase) { + log.info( + `Content not from webpack is served from ${colors.info(useColor, contentBase)}` + ); + } + + if (options.historyApiFallback) { + log.info( + `404s will fallback to ${colors.info(useColor, options.historyApiFallback.index || '/index.html')}` + ); + } + + if (options.bonjour) { + log.info( + 'Broadcasting "http" with subtype of "webpack" via ZeroConf DNS (Bonjour)' + ); + } +} + +module.exports = logStatus; diff --git a/lib/utils/open.js b/lib/utils/open.js new file mode 100644 index 0000000000..b27f3c5ddd --- /dev/null +++ b/lib/utils/open.js @@ -0,0 +1,25 @@ +'use strict'; + +const opn = require('opn'); + +function open(uri, options, log) { + if (!options.open) { + return; + } + + let openOptions = {}; + let openMessage = 'Unable to open browser'; + + if (typeof options.open === 'string') { + openOptions = { app: options.open }; + openMessage += `: ${options.open}`; + } + + opn(uri + (options.openPage || ''), openOptions).catch(() => { + log.warn( + `${openMessage}. If you are running in a headless environment, please do not use the --open flag` + ); + }); +} + +module.exports = open;