1 | var http = require('http');
|
2 | var WebSocketServer = require('ws').Server;
|
3 | var url = require('url');
|
4 |
|
5 | var LiveReload = function (port) {
|
6 | this.httpServer = http.createServer();
|
7 | this.httpServer.on('request', this.onRequest.bind(this));
|
8 | this.httpServer.listen(port);
|
9 |
|
10 | this.webSocketServer = new WebSocketServer({
|
11 | server: this.httpServer,
|
12 | path: '/livereload'
|
13 | });
|
14 | this.webSocketServer.on('connection', this.onConnect.bind(this));
|
15 | this.webSocketClientMap = {};
|
16 |
|
17 | this.lastModifyTimestampMap = {};
|
18 | };
|
19 |
|
20 | LiveReload.prototype.onConnect = function (client) {
|
21 | var liveReload = this;
|
22 | client.on('message', function incoming(message) {
|
23 | message = JSON.parse(message);
|
24 | var srcPath = message.srcPath;
|
25 | var timestamp = message.timestamp;
|
26 |
|
27 | var lastModifyTimestamp = liveReload.lastModifyTimestampMap[srcPath];
|
28 | if (lastModifyTimestamp && lastModifyTimestamp > timestamp) {
|
29 | try {
|
30 | client.send(JSON.stringify({
|
31 | isExpire: true
|
32 | }));
|
33 | } catch (err) {
|
34 | }
|
35 | return;
|
36 | }
|
37 |
|
38 | var clientList = liveReload.webSocketClientMap[srcPath] || [];
|
39 | clientList.push(client);
|
40 |
|
41 | liveReload.webSocketClientMap[srcPath] = clientList;
|
42 |
|
43 | client.on('close', function close() {
|
44 | var index = clientList.indexOf(client);
|
45 | if (index !== -1) {
|
46 | clientList.splice(clientList.indexOf(client), 1);
|
47 | }
|
48 | });
|
49 | });
|
50 | };
|
51 |
|
52 | LiveReload.prototype.onRequest = function (request, response) {
|
53 | var urlObj = url.parse(request.url, true);
|
54 |
|
55 | if (urlObj.pathname !== '/livereload') {
|
56 | response.statusCode = 404;
|
57 | response.end();
|
58 | return;
|
59 | }
|
60 |
|
61 | var query = urlObj.query || {};
|
62 | var srcPath = query.srcpath;
|
63 | var timestamp = query.timestamp;
|
64 | var callback = query.callback;
|
65 | var isExpire = false;
|
66 |
|
67 | if (srcPath && timestamp) {
|
68 | var lastModifyTimestamp = this.lastModifyTimestampMap[srcPath];
|
69 | if (lastModifyTimestamp && lastModifyTimestamp > timestamp) {
|
70 | isExpire = true;
|
71 | }
|
72 | }
|
73 |
|
74 | if (callback) {
|
75 | response.end(callback + '(' + (isExpire ? 'true' : 'false') + ');');
|
76 | } else {
|
77 | response.end(JSON.stringify({
|
78 | isExpire: isExpire
|
79 | }));
|
80 | }
|
81 | };
|
82 |
|
83 | LiveReload.prototype.change = function (srcPath, modifyTime) {
|
84 | this.lastModifyTimestampMap[srcPath] = modifyTime;
|
85 |
|
86 | var clientList = this.webSocketClientMap[srcPath];
|
87 |
|
88 | if (clientList && clientList.length) {
|
89 | clientList.forEach(function (client) {
|
90 | try {
|
91 | client.send(JSON.stringify({
|
92 | isExpire: true
|
93 | }));
|
94 | } catch (err) {
|
95 | }
|
96 | });
|
97 | }
|
98 | };
|
99 |
|
100 | module.exports = LiveReload;
|