webpack-plugin-serve
Version:
A Development Server in a Webpack Plugin
97 lines (75 loc) • 2.33 kB
JavaScript
/*
Copyright © 2018 Andrew Powell
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of this Source Code Form.
*/
const { error, refresh, warn } = require('./log')();
// ignore 1008 (HTTP 400 equivalent) and 1011 (HTTP 500 equivalent)
const ignoreCodes = [1008, 1011];
const maxAttempts = 10;
class ClientSocket {
constructor(options, ...args) {
this.args = args;
this.attempts = 0;
this.eventHandlers = [];
this.options = options;
this.retrying = false;
this.connect();
}
addEventListener(...args) {
this.eventHandlers.push(args);
this.socket.addEventListener(...args);
}
close() {
this.socket.close();
}
connect() {
if (this.socket) {
delete this.socket;
}
this.connecting = true;
this.socket = new WebSocket(...this.args);
if (this.options.retry) {
this.socket.addEventListener('close', (event) => {
if (ignoreCodes.includes(event.code)) {
return;
}
if (!this.retrying) {
warn(`The WebSocket was closed and will attempt to reconnect`);
}
this.reconnect();
});
} else {
this.socket.onclose = () => warn(`The client WebSocket was closed. ${refresh}`);
}
this.socket.addEventListener('open', () => {
this.attempts = 0;
this.retrying = false;
});
if (this.eventHandlers.length) {
for (const [name, fn] of this.eventHandlers) {
this.socket.addEventListener(name, fn);
}
}
}
reconnect() {
this.attempts += 1;
this.retrying = true;
if (this.attempts > maxAttempts) {
error(`The WebSocket could not be reconnected. ${refresh}`);
this.retrying = false;
return;
}
const timeout = 1000 * this.attempts ** 2;
setTimeout(() => this.connect(this.args), timeout);
}
removeEventListener(...args) {
const [, handler] = args;
this.eventHandlers = this.eventHandlers.filter(([, fn]) => fn === handler);
this.socket.removeEventListener(...args);
}
}
module.exports = { ClientSocket };