diff --git a/lib/utils/develop.js b/lib/utils/develop.js index daa6e7c307c9e..103f34c6a9f1e 100644 --- a/lib/utils/develop.js +++ b/lib/utils/develop.js @@ -1,5 +1,6 @@ /* @flow weak */ require('node-cjsx').transform() +import detect from 'detect-port' import Hapi from 'hapi' import Boom from 'boom' import React from 'react' @@ -13,13 +14,20 @@ import WebpackPlugin from 'hapi-webpack-plugin' import opn from 'opn' import fs from 'fs' import glob from 'glob' +import rl from 'readline' + +const rlInterface = rl.createInterface({ + input: process.stdin, + output: process.stdout, +}) import globPages from './glob-pages' import webpackConfig from './webpack.config' const debug = require('debug')('gatsby:application') -module.exports = (program) => { +function startServer (program, launchPort) { const directory = program.directory + const serverPort = launchPort || program.port // Load pages for the site. return globPages(directory, (err, pages) => { @@ -46,11 +54,11 @@ module.exports = (program) => { const HTML = factory() debug('Configuring develop server') - // Setup and start Hapi to serve html + static files + webpack-hot-middleware. const server = new Hapi.Server() + server.connection({ host: program.host, - port: program.port, + port: serverPort, }) server.route({ @@ -82,7 +90,7 @@ module.exports = (program) => { path: '/{path*}', handler: { directory: { - path: `${directory}/pages`, + path: `${program.directory}/pages`, listing: false, index: false, }, @@ -96,7 +104,7 @@ module.exports = (program) => { const parsed = parsePath(request.path) const page = _.find(pages, (p) => p.path === (`${parsed.dirname}/`)) - let absolutePath = `${directory}/pages` + let absolutePath = `${program.directory}/pages` let path if (page) { path = `/${parsePath(page.requirePath).dirname}/${parsed.basename}` @@ -145,7 +153,7 @@ module.exports = (program) => { }, } - server.register({ + return server.register({ register: WebpackPlugin, options: { compiler, @@ -161,20 +169,13 @@ module.exports = (program) => { server.start((e) => { if (e) { if (e.code === 'EADDRINUSE') { - const finder = require('process-finder') - finder.find({ elevate: false, port: program.port }, (startErr, pids) => { - const msg = -`We were unable to start Gatsby on port ${program.port} as there's already a process -listening on that port (PID: ${pids[0]}). You can either use a different port -(e.g. gatsby develop --port ${parseInt(program.port, 10) + 1}) or stop the process already listening -on your desired port.` - console.log(msg) - process.exit() - }) + // eslint-disable-next-line max-len + console.log(`Unable to start Gatsby on port ${serverPort} as there's already a process listing on that port.`) } else { console.log(e) - process.exit() } + + process.exit() } else { if (program.open) { opn(server.info.uri) @@ -186,3 +187,28 @@ on your desired port.` }) }) } + +module.exports = (program) => { + detect(program.port, (err, _port) => { + if (err) { + console.error(err) + process.exit() + } + + if (program.port !== _port) { + // eslint-disable-next-line max-len + const question = `Something is already running at port ${program.port} \nWould you like to run the app at another port instead? [Y/n] ` + + return rlInterface.question(question, (answer) => { + let launchPort = program.port + if (answer.length === 0 || answer.match(/^yes|y$/i)) { + launchPort = _port + } + + return startServer(program, launchPort) + }) + } + + return startServer(program) + }) +} diff --git a/lib/utils/serve-build.js b/lib/utils/serve-build.js index 57fa03808c2c1..5caa02611149e 100644 --- a/lib/utils/serve-build.js +++ b/lib/utils/serve-build.js @@ -1,21 +1,26 @@ /* @flow weak */ +import detect from 'detect-port' import Hapi from 'hapi' import opn from 'opn' +import rl from 'readline' + +const rlInterface = rl.createInterface({ + input: process.stdin, + output: process.stdout, +}) const debug = require('debug')('gatsby:application') -module.exports = (program) => { +function startServer (program, launchPort) { const directory = program.directory + const serverPort = launchPort || program.port debug('Serving /public') - - // Setup and start Hapi to static files. - const server = new Hapi.Server() server.connection({ host: program.host, - port: program.port, + port: serverPort, }) server.route({ @@ -34,19 +39,13 @@ module.exports = (program) => { server.start((e) => { if (e) { if (e.code === 'EADDRINUSE') { - const finder = require('process-finder') - finder.find({ elevate: false, port: program.port }, (startErr, pids) => { - const msg = -`We were unable to start Gatsby on port ${program.port} as there's already a process -listening on that port (PID: ${pids[0]}). You can either use a different port -(e.g. gatsby serve-build --port ${parseInt(program.port, 10) + 1}) or stop the process -already listening on your desired port.` - console.log(msg) - process.exit() - }) + // eslint-disable-next-line max-len + console.log(`Unable to start Gatsby on port ${serverPort} as there's already a process listing on that port.`) } else { console.log(e) } + + process.exit() } else { if (program.open) { opn(server.info.uri) @@ -55,3 +54,28 @@ already listening on your desired port.` } }) } + +module.exports = (program) => { + detect(program.port, (err, _port) => { + if (err) { + console.error(err) + process.exit() + } + + if (program.port !== _port) { + // eslint-disable-next-line max-len + const question = `Something is already running at port ${program.port} \nWould you like to run the app at another port instead? [Y/n] ` + + return rlInterface.question(question, (answer) => { + let launchPort = program.port + if (answer.length === 0 || answer.match(/^yes|y$/i)) { + launchPort = _port + } + + return startServer(program, launchPort) + }) + } + + return startServer(program) + }) +} diff --git a/package.json b/package.json index 3e556351ce706..0c32e81708454 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "commander": "^2.9.0", "css-loader": "^0.23.1", "debug": "^2.2.0", + "detect-port": "^1.0.0", "extract-text-webpack-plugin": "^1.0.1", "file-loader": "^0.9.0", "front-matter": "^2.1.0", @@ -58,7 +59,6 @@ "postcss-import": "^8.1.2", "postcss-loader": "^0.9.1", "postcss-reporter": "^1.4.1", - "process-finder": "^1.0.0", "raw-loader": "^0.5.1", "react": "^15.3.0", "react-document-title": "^2.0.1",