In live reloading, also reload if the server is being recycled. Plus rewrite LiveReloading.ts completely to be better organized.
This commit is contained in:
parent
de4d78f454
commit
f1283940b7
|
|
@ -1,38 +1,78 @@
|
||||||
export function enableLiveReloading(endpointUri: string) {
|
const pollIntervalMs = 500;
|
||||||
listenForReloadEvent(endpointUri);
|
const maxPollDurationMs = 10 * 1000;
|
||||||
|
|
||||||
|
export function enableLiveReloading(endpointUri: string) {
|
||||||
|
new ReloadContext(endpointUri).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
function listenForReloadEvent(endpointUri: string) {
|
class ReloadContext {
|
||||||
if (!WebSocket) {
|
private _websocketUri: string;
|
||||||
console.log('Browser does not support WebSocket, so live reloading will be disabled.');
|
private _didConnect = false;
|
||||||
return;
|
private _pollUntilConnectedThenReload = false;
|
||||||
|
private _stopPollingAtTime: Date | null = null;
|
||||||
|
|
||||||
|
constructor(endpointUri: string) {
|
||||||
|
this._websocketUri = toAbsoluteWebSocketUri(endpointUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, connect to the endpoint
|
start() {
|
||||||
const websocketUri = toAbsoluteWebSocketUri(endpointUri);
|
if (typeof WebSocket !== 'undefined') {
|
||||||
const source = new WebSocket(websocketUri);
|
this._attemptToConnect(/* delay */ 0);
|
||||||
let allowConnectionFailedErrorReporting = true;
|
} else {
|
||||||
|
console.log('Browser does not support WebSocket, so live reloading will be disabled.');
|
||||||
source.onopen = e => {
|
|
||||||
allowConnectionFailedErrorReporting = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
source.onerror = e => {
|
|
||||||
if (allowConnectionFailedErrorReporting) {
|
|
||||||
allowConnectionFailedErrorReporting = false;
|
|
||||||
console.error(`The client app was compiled with live reloading enabled, but could not open `
|
|
||||||
+ ` a WebSocket connection to the server at ${websocketUri}\n`
|
|
||||||
+ `To fix this inconsistency, either run the server in development mode, or compile the `
|
|
||||||
+ `client app in Release configuration.`);
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// If we're notified that we should reload, then do so
|
private _attemptToConnect(delayMs: number) {
|
||||||
source.onmessage = e => {
|
setTimeout(() => {
|
||||||
if (e.data === 'reload') {
|
const source = new WebSocket(this._websocketUri);
|
||||||
location.reload();
|
source.onopen = event => this._onOpen();
|
||||||
|
source.onmessage = event => this._onMessage(event.data);
|
||||||
|
source.onerror = event => this._onError();
|
||||||
|
source.onclose = event => this._onClose();
|
||||||
|
}, delayMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onOpen() {
|
||||||
|
this._didConnect = true;
|
||||||
|
|
||||||
|
if (this._pollUntilConnectedThenReload) {
|
||||||
|
reloadNow();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
private _onMessage(data: string) {
|
||||||
|
if (data === 'reload') {
|
||||||
|
reloadNow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onClose() {
|
||||||
|
if (this._didConnect) {
|
||||||
|
// Looks like the server is being recycled (or possibly just shut down, but in the
|
||||||
|
// absence of a graceful shutdown we have no way to tell the difference)
|
||||||
|
// Wait until the server appears to be back, then reload
|
||||||
|
this._pollUntilConnectedThenReload = true;
|
||||||
|
this._stopPollingAtTime = new Date(new Date().valueOf() + maxPollDurationMs);
|
||||||
|
this._attemptToConnect(/* delay */ pollIntervalMs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onError() {
|
||||||
|
if (!this._didConnect) {
|
||||||
|
if (this._pollUntilConnectedThenReload) {
|
||||||
|
if (new Date() < this._stopPollingAtTime!) {
|
||||||
|
// Continue polling
|
||||||
|
this._attemptToConnect(/* delay */ pollIntervalMs);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error(`The client app was compiled with live reloading enabled, but could not open `
|
||||||
|
+ ` a WebSocket connection to the server at ${this._websocketUri}\n`
|
||||||
|
+ `To fix this inconsistency, either run the server in development mode, or compile the `
|
||||||
|
+ `client app in Release configuration.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toAbsoluteWebSocketUri(uri: string) {
|
function toAbsoluteWebSocketUri(uri: string) {
|
||||||
|
|
@ -46,3 +86,7 @@ function toAbsoluteWebSocketUri(uri: string) {
|
||||||
// Scheme must be ws: or wss:
|
// Scheme must be ws: or wss:
|
||||||
return uri.replace(/^http/, 'ws');
|
return uri.replace(/^http/, 'ws');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function reloadNow() {
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue