create-js-app-scripts
Version:
Configuration and scripts for Create Js App.
116 lines (92 loc) • 3.46 kB
JavaScript
/* @flow */
const openBrowser = require('../utils/openBrowser');
const path = require('path');
function createHotServer(compiler /*: Object */, eventEmitter /*: events$EventEmitter */) /*: ServerManager */ {
const sockets = {
id: 0,
connections: {}
};
let runningServer;
compiler.plugin('done', stats => {
if (stats.hasErrors()) {
eventEmitter.emit('server-log-error', 'Build has errors, keeping previous build running');
return;
}
if (stats.hasWarnings()) {
eventEmitter.emit('server-log-warning', 'Build compiled with warnings');
} else {
eventEmitter.emit('server-log-success', 'Build succeeded');
}
// Make sure our newly built server bundles aren't in the module cache.
Object.keys(require.cache).forEach(modulePath => {
if (~modulePath.indexOf(compiler.options.output.path)) {
delete require.cache[modulePath];
}
});
const compiledOutputPath = path.resolve(
compiler.options.output.path, `${Object.keys(compiler.options.entry)[0]}.js`
);
// First try to close previous server so we don't have conflict in ports
// then require new server (it will automatically start new server)
const closePreviousServer = new Promise(resolve => {
if (runningServer) {
eventEmitter.emit('server-log', 'Restarting server');
// destroy all connections
for (const socketId in sockets.connections) {
sockets.connections[socketId].destroy();
}
runningServer.close(resolve);
return;
}
resolve();
});
const startServer = closePreviousServer.then(
() => new Promise((resolve, reject) => {
try {
const shouldOpenBrowser = !runningServer;
runningServer = require(compiledOutputPath).default;
if (!runningServer) {
eventEmitter.emit(
'server-log-error',
'Server bundle did not export a listener. Please export listener using `export default` syntax'
);
} else if (typeof runningServer.on !== 'function') {
eventEmitter.emit(
'server-log-error',
'Cannot attach connection handler to listener because it is missing an `on` method'
);
}
// listen to all connections, we need this to close server
runningServer.on('connection', socket => {
const socketId = sockets.id++;
sockets.connections[socketId] = socket;
socket.on('close', () => delete sockets.connections[socketId]);
});
const url = `http://localhost:${process.env.SERVER_PORT || 3000}`;
eventEmitter.emit('server-log-info', `Server is listening on ${url}`);
shouldOpenBrowser && openBrowser(url);
} catch (err) {
reject(err);
}
resolve();
}),
err => {
eventEmitter.emit('server-log-error', 'Error closing previous server');
eventEmitter.emit('server-error', err);
}
);
startServer.catch(err => {
eventEmitter.emit('server-log-error', 'Server bundle is invalid, server is not running');
eventEmitter.emit('server-error', err);
});
});
return {
close() {
if (runningServer) {
return new Promise(resolve => runningServer.close(resolve));
}
return Promise.resolve();
}
};
}
module.exports = createHotServer;