forked from parcel-bundler/parcel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHMRServer.js
105 lines (90 loc) · 2.5 KB
/
HMRServer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
const http = require('http');
const https = require('https');
const WebSocket = require('ws');
const prettyError = require('./utils/prettyError');
const generateCertificate = require('./utils/generateCertificate');
const getCertificate = require('./utils/getCertificate');
const logger = require('./Logger');
class HMRServer {
async start(options = {}) {
await new Promise(async resolve => {
if (!options.https) {
this.server = http.createServer();
} else if (typeof options.https === 'boolean') {
this.server = https.createServer(generateCertificate(options));
} else {
this.server = https.createServer(await getCertificate(options.https));
}
this.wss = new WebSocket.Server({server: this.server});
this.server.listen(options.hmrPort, resolve);
});
this.wss.on('connection', ws => {
ws.onerror = this.handleSocketError;
if (this.unresolvedError) {
ws.send(JSON.stringify(this.unresolvedError));
}
});
this.wss.on('error', this.handleSocketError);
return this.wss._server.address().port;
}
stop() {
this.wss.close();
this.server.close();
}
emitError(err) {
let {message, stack} = prettyError(err);
// store the most recent error so we can notify new connections
// and so we can broadcast when the error is resolved
this.unresolvedError = {
type: 'error',
error: {
message,
stack
}
};
this.broadcast(this.unresolvedError);
}
emitUpdate(assets) {
if (this.unresolvedError) {
this.unresolvedError = null;
this.broadcast({
type: 'error-resolved'
});
}
const containsHtmlAsset = assets.some(asset => asset.type === 'html');
if (containsHtmlAsset) {
this.broadcast({
type: 'reload'
});
} else {
this.broadcast({
type: 'update',
assets: assets.map(asset => {
let deps = {};
for (let [dep, depAsset] of asset.depAssets) {
deps[dep.name] = depAsset.id;
}
return {
id: asset.id,
generated: asset.generated,
deps: deps
};
})
});
}
}
handleSocketError(err) {
if (err.error.code === 'ECONNRESET') {
// This gets triggered on page refresh, ignore this
return;
}
logger.warn(err);
}
broadcast(msg) {
const json = JSON.stringify(msg);
for (let ws of this.wss.clients) {
ws.send(json);
}
}
}
module.exports = HMRServer;