Skip to content

Commit

Permalink
User friendly server errors and automatic port switching (#164)
Browse files Browse the repository at this point in the history
* more userfriendly server errors and automatically asign free port if port is busy

* cleanup code a lil

* fix typo

* remove unused import

* minor improvements

* change double quotes into single quotes

* lil cleanup & restructuring

* bugfixes
  • Loading branch information
Jasper De Moor authored and devongovett committed Dec 11, 2017
1 parent dc52638 commit 87350f4
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 13 deletions.
4 changes: 2 additions & 2 deletions bin/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ if (!args[2] || !program.commands.some(c => c.name() === args[2])) {

program.parse(args);

function bundle(main, command) {
async function bundle(main, command) {
// Require bundler here so the help command is fast
const Bundler = require('../');

Expand All @@ -94,7 +94,7 @@ function bundle(main, command) {
const bundler = new Bundler(main, command);

if (command.name() === 'serve') {
const server = bundler.serve(command.port || 1234);
const server = await bundler.serve(command.port || 1234);
if (command.open) {
require('opn')(`http://localhost:${server.address().port}`);
}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"chokidar": "^1.7.0",
"commander": "^2.11.0",
"cssnano": "^3.10.0",
"get-port": "^3.2.0",
"glob": "^7.1.2",
"htmlnano": "^0.1.6",
"is-url": "^1.2.2",
Expand Down
8 changes: 3 additions & 5 deletions src/Bundler.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const {EventEmitter} = require('events');
const Logger = require('./Logger');
const PackagerRegistry = require('./packagers');
const localRequire = require('./utils/localRequire');
const customErrors = require('./utils/customErrors');

/**
* The Bundler is the main entry point. It resolves and loads assets,
Expand Down Expand Up @@ -452,12 +453,9 @@ class Bundler extends EventEmitter {
return Server.middleware(this);
}

serve(port = 1234) {
this.logger.persistent(
'Server running at ' + this.logger.chalk.cyan(`http://localhost:${port}`)
);
async serve(port = 1234) {
this.bundle();
return Server.serve(this, port);
return await Server.serve(this, port);
}
}

Expand Down
27 changes: 25 additions & 2 deletions src/Server.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ const http = require('http');
const path = require('path');
const url = require('url');
const serveStatic = require('serve-static');
const getPort = require('get-port');
const serverErrors = require('./utils/customErrors').serverErrors;

function middleware(bundler) {
const serve = serveStatic(bundler.options.outDir, {index: false});
Expand Down Expand Up @@ -54,8 +56,29 @@ function middleware(bundler) {
};
}

function serve(bundler, port) {
return http.createServer(middleware(bundler)).listen(port);
async function serve(bundler, port) {
let freePort = await getPort({port});
let server = http.createServer(middleware(bundler)).listen(freePort);

server.on('error', err => {
bundler.logger.error(new Error(serverErrors(err, server.address().port)));
});

server.once('listening', connection => {
let addon =
server.address().port !== port
? `- ${bundler.logger.chalk.red(
`configured port ${port} could not be used.`
)}`
: '';
bundler.logger.persistent(
`Server running at ${bundler.logger.chalk.cyan(
`http://localhost:${server.address().port}`
)} ${addon}\n`
);
});

return server;
}

exports.middleware = middleware;
Expand Down
16 changes: 16 additions & 0 deletions src/utils/customErrors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
let serverErrorList = {
EACCES: "You don't have access to bind the server to port {port}.",
EADDRINUSE: 'There is already a process listening on port {port}.'
};

function serverErrors(err, port) {
let desc = serverErrorList[err.code].replace(/{port}/g, port);
if (!desc) {
desc = `Error: ${
err.code
} occurred while setting up server on port ${port}.`;
}
return desc;
}

module.exports.serverErrors = serverErrors;
8 changes: 4 additions & 4 deletions test/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ describe('server', function() {

it('should serve files', async function() {
let b = bundler(__dirname + '/integration/commonjs/index.js');
server = b.serve(0);
server = await b.serve(0);

let data = await get('/dist/index.js');
assert.equal(data, fs.readFileSync(__dirname + '/dist/index.js', 'utf8'));
});

it('should serve a default page if the main bundle is an HTML asset', async function() {
let b = bundler(__dirname + '/integration/html/index.html');
server = b.serve(0);
server = await b.serve(0);

let data = await get('/');
assert.equal(data, fs.readFileSync(__dirname + '/dist/index.html', 'utf8'));
Expand All @@ -50,7 +50,7 @@ describe('server', function() {

it('should serve a 404 if the file does not exist', async function() {
let b = bundler(__dirname + '/integration/commonjs/index.js');
server = b.serve(0);
server = await b.serve(0);

let threw = false;
try {
Expand All @@ -64,7 +64,7 @@ describe('server', function() {

it('should serve a 500 if the bundler errored', async function() {
let b = bundler(__dirname + '/integration/html/index.html');
server = b.serve(0);
server = await b.serve(0);

b.errored = true;

Expand Down
4 changes: 4 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1900,6 +1900,10 @@ get-own-enumerable-property-symbols@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-2.0.1.tgz#5c4ad87f2834c4b9b4e84549dc1e0650fb38c24b"

get-port@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc"

get-stdin@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
Expand Down

0 comments on commit 87350f4

Please sign in to comment.