Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 44 additions & 83 deletions lib/Server.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,76 +43,36 @@ class Server {

this.compiler = compiler;
this.options = options;

this.sockets = [];
this.contentBaseWatchers = [];
// Keep track of websocket proxies for external websocket upgrade.
this.websocketProxies = [];
this.log = _log || createLogger(options);

if (this.options.transportMode !== undefined) {
this.log.warn(
'transportMode is an experimental option, meaning its usage could potentially change without warning'
);
}
// this value of ws can be overwritten for tests
this.wsHeartbeatInterval = 30000;

normalizeOptions(this.compiler, this.options);

// don't move this position because addEntries called by updateCompiler checks this.options.hot|hotOnly
this.options.hot =
typeof this.options.hot === 'boolean' || this.options.hot === 'only'
? this.options.hot
: true;

updateCompiler(this.compiler, this.options);

this.heartbeatInterval = 30000;
// this.SocketServerImplementation is a class, so it must be instantiated before use
this.socketServerImplementation = getSocketServerImplementation(
this.SocketServerImplementation = getSocketServerImplementation(
this.options
);

this.originalStats =
this.options.stats && Object.keys(this.options.stats).length
? this.options.stats
: {};

this.sockets = [];
this.contentBaseWatchers = [];

// TODO this.<property> is deprecated (remove them in next major release.) in favor this.options.<property>
this.headers = this.options.headers;
this.progress = this.options.progress;

this.serveIndex = this.options.serveIndex;

this.clientOverlay = this.options.overlay;
this.clientLogLevel = this.options.clientLogLevel;

this.publicHost = this.options.public;
this.allowedHosts = this.options.allowedHosts;
this.disableHostCheck = !!this.options.disableHostCheck;

this.watchOptions = options.watchOptions || {};

if (this.progress) {
if (this.options.progress) {
this.setupProgressPlugin();
}

this.setupHooks();
this.setupApp();
this.setupCheckHostRoute();
this.setupDevMiddleware();

// set express routes
routes(this);

// Keep track of websocket proxies for external websocket upgrade.
this.websocketProxies = [];

this.setupFeatures();
this.setupHttps();
this.createServer();

routes(this);
killable(this.listeningApp);

// Proxy websockets without the initial http request
// Proxy WebSocket without the initial http request
// https://github.com/chimurai/http-proxy-middleware#external-websocket-upgrade
this.websocketProxies.forEach(function (wsProxy) {
this.listeningApp.on('upgrade', wsProxy.upgrade);
Expand Down Expand Up @@ -163,8 +123,8 @@ class Server {
compile.tap('webpack-dev-server', invalidPlugin);
invalid.tap('webpack-dev-server', invalidPlugin);
done.tap('webpack-dev-server', (stats) => {
this._sendStats(this.sockets, this.getStats(stats));
this._stats = stats;
this.sendStats(this.sockets, this.getStats(stats));
this.stats = stats;
});
};

Expand Down Expand Up @@ -534,10 +494,7 @@ class Server {
}
}

// checking if it's set to true or not set (Default : undefined => true)
this.serveIndex = this.serveIndex || this.serveIndex === undefined;

if (this.options.contentBase && this.serveIndex) {
if (this.options.contentBase && this.options.serveIndex) {
runnableFeatures.push('contentBaseIndex');
}

Expand Down Expand Up @@ -625,8 +582,7 @@ class Server {
}

createSocketServer() {
const SocketServerImplementation = this.socketServerImplementation;
this.socketServer = new SocketServerImplementation(this);
this.socketServer = new this.SocketServerImplementation(this);

this.socketServer.onConnection((connection, headers) => {
if (!connection) {
Expand Down Expand Up @@ -658,8 +614,8 @@ class Server {
}
});

if (this.clientLogLevel) {
this.sockWrite([connection], 'log-level', this.clientLogLevel);
if (this.options.clientLogLevel) {
this.sockWrite([connection], 'log-level', this.options.clientLogLevel);
}

if (this.options.hot === true || this.options.hot === 'only') {
Expand All @@ -671,19 +627,19 @@ class Server {
this.sockWrite([connection], 'liveReload', this.options.liveReload);
}

if (this.progress) {
this.sockWrite([connection], 'progress', this.progress);
if (this.options.progress) {
this.sockWrite([connection], 'progress', this.options.progress);
}

if (this.clientOverlay) {
this.sockWrite([connection], 'overlay', this.clientOverlay);
if (this.options.clientOverlay) {
this.sockWrite([connection], 'overlay', this.options.clientOverlay);
}

if (!this._stats) {
if (!this.stats) {
return;
}

this._sendStats([connection], this.getStats(this._stats), true);
this.sendStats([connection], this.getStats(this.stats), true);
});
}

Expand Down Expand Up @@ -755,8 +711,8 @@ class Server {
getStats(statsObj) {
const stats = Server.DEFAULT_STATS;

if (this.originalStats.warningsFilter) {
stats.warningsFilter = this.originalStats.warningsFilter;
if (this.options.stats.warningsFilter) {
stats.warningsFilter = this.options.stats.warningsFilter;
}

return statsObj.toJson(stats);
Expand All @@ -768,10 +724,10 @@ class Server {
}

setContentHeaders(req, res, next) {
if (this.headers) {
if (this.options.headers) {
// eslint-disable-next-line
for (const name in this.headers) {
res.setHeader(name, this.headers[name]);
for (const name in this.options.headers) {
res.setHeader(name, this.options.headers[name]);
}
}

Expand All @@ -788,7 +744,7 @@ class Server {

checkHeaders(headers, headerToCheck) {
// allow user to opt-out this security check, at own risk
if (this.disableHostCheck) {
if (this.options.disableHostCheck) {
return true;
}

Expand Down Expand Up @@ -828,11 +784,14 @@ class Server {
if (isValidHostname) {
return true;
}

const allowedHosts = this.options.allowedHosts;

// always allow localhost host, for convenience
// allow if hostname is in allowedHosts
if (this.allowedHosts && this.allowedHosts.length) {
for (let hostIdx = 0; hostIdx < this.allowedHosts.length; hostIdx++) {
const allowedHost = this.allowedHosts[hostIdx];
if (allowedHosts && allowedHosts.length) {
for (let hostIdx = 0; hostIdx < allowedHosts.length; hostIdx++) {
const allowedHost = allowedHosts[hostIdx];

if (allowedHost === hostname) {
return true;
Expand All @@ -854,10 +813,12 @@ class Server {
}

// also allow public hostname if provided
if (typeof this.publicHost === 'string') {
const idxPublic = this.publicHost.indexOf(':');
if (typeof this.options.public === 'string') {
const idxPublic = this.options.public.indexOf(':');
const publicHostname =
idxPublic >= 0 ? this.publicHost.substr(0, idxPublic) : this.publicHost;
idxPublic >= 0
? this.options.public.substr(0, idxPublic)
: this.options.public;

if (hostname === publicHostname) {
return true;
Expand Down Expand Up @@ -896,7 +857,7 @@ class Server {
}

// send stats to a socket or multiple sockets
_sendStats(sockets, stats, force) {
sendStats(sockets, stats, force) {
const shouldEmit =
!force &&
stats &&
Expand All @@ -923,10 +884,10 @@ class Server {
// duplicate the same massaging of options that watchpack performs
// https://github.com/webpack/watchpack/blob/master/lib/DirectoryWatcher.js#L49
// this isn't an elegant solution, but we'll improve it in the future
const usePolling = this.watchOptions.poll ? true : undefined;
const usePolling = this.options.watchOptions.poll ? true : undefined;
const interval =
typeof this.watchOptions.poll === 'number'
? this.watchOptions.poll
typeof this.options.watchOptions.poll === 'number'
? this.options.watchOptions.poll
: undefined;

const watchOptions = {
Expand All @@ -936,7 +897,7 @@ class Server {
atomic: false,
alwaysStat: true,
ignorePermissionErrors: true,
ignored: this.watchOptions.ignored,
ignored: this.options.watchOptions.ignored,
usePolling,
interval,
};
Expand Down
2 changes: 1 addition & 1 deletion lib/servers/WebsocketServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ module.exports = class WebsocketServer extends BaseServer {
socket.isAlive = false;
socket.ping(noop);
});
}, this.server.heartbeatInterval);
}, this.server.wsHeartbeatInterval);
}

send(connection, message) {
Expand Down
13 changes: 11 additions & 2 deletions lib/utils/normalizeOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,18 @@ function normalizeOptions(compiler, options) {
// Setup default value
options.contentBase =
options.contentBase !== undefined ? options.contentBase : process.cwd();

// Setup default value
options.contentBasePublicPath = options.contentBasePublicPath || '/';
options.hot =
typeof options.hot === 'boolean' || options.hot === 'only'
? options.hot
: true;
options.serveIndex =
options.serveIndex !== undefined ? options.serveIndex : true;
options.watchOptions = options.watchOptions || {};
options.stats =
options.stats && Object.keys(options.stats).length !== 0
? options.stats
: {};

// normalize transportMode option
if (options.transportMode === undefined) {
Expand Down
2 changes: 1 addition & 1 deletion test/server/servers/WebsocketServer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe('WebsocketServer', () => {
},
},
listeningApp,
heartbeatInterval: 800,
wsHeartbeatInterval: 800,
};
socketServer = new WebsocketServer(server);
done();
Expand Down
Loading