Skip to content

Commit

Permalink
Replace socket.io with SockJS as discussed in webpack#229
Browse files Browse the repository at this point in the history
This removes the node-gyp dependency :).

Fixes webpack#229, webpack#276, fixes webpack#195, fixes webpack#267, fixes webpack#258 and fixes webpack#242
  • Loading branch information
SpaceK33z committed Oct 24, 2015
1 parent 24b356e commit 7dcd41d
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 139 deletions.
84 changes: 28 additions & 56 deletions client/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
var url = require('url');
var io = require("socket.io-client");
var SockJS = require("sockjs-client");
var stripAnsi = require('strip-ansi');
var scriptElements = document.getElementsByTagName("script");

Expand All @@ -8,70 +8,42 @@ var urlParts = url.parse(typeof __resourceQuery === "string" && __resourceQuery
scriptElements[scriptElements.length-1].getAttribute("src").replace(/\/[^\/]+$/, "")
);

io = io.connect(
url.format({
var recInterval = null;
var sock = null;

var newConnection = function() {
sock = new SockJS(url.format({
protocol: urlParts.protocol,
auth: urlParts.auth,
hostname: (urlParts.hostname === '0.0.0.0') ? window.location.hostname : urlParts.hostname,
port: urlParts.port
}), {
path: urlParts.path === '/' ? null : urlParts.path
}
);

var hot = false;
var initial = true;
var currentHash = "";
port: urlParts.port,
pathname: urlParts.path === '/' ? "/sockjs-node" : urlParts.path
}));

io.on("hot", function() {
hot = true;
console.log("[WDS] Hot Module Replacement enabled.");
});
clearInterval(recInterval);

io.on("invalid", function() {
console.log("[WDS] App updated. Recompiling...");
});
sock.onclose = function() {
console.error("[WDS] Disconnected!");

io.on("hash", function(hash) {
currentHash = hash;
});
// Try to reconnect.
sock = null;
recInterval = setInterval(function () {
newConnection();
}, 2000);
};

io.on("still-ok", function() {
console.log("[WDS] Nothing changed.")
});
sock.onmessage = function(e) {
// This assumes that all data sent via the websocket is JSON.
var msg = JSON.parse(e.data);
onSocketMsg[msg.type](msg.data);
};
};

io.on("ok", function() {
if(initial) return initial = false;
reloadApp();
});
newConnection();

io.on("warnings", function(warnings) {
console.log("[WDS] Warnings while compiling.");
for(var i = 0; i < warnings.length; i++)
console.warn(stripAnsi(warnings[i]));
if(initial) return initial = false;
reloadApp();
});

io.on("errors", function(errors) {
console.log("[WDS] Errors while compiling.");
for(var i = 0; i < errors.length; i++)
console.error(stripAnsi(errors[i]));
if(initial) return initial = false;
reloadApp();
});

io.on("proxy-error", function(errors) {
console.log("[WDS] Proxy error.");
for(var i = 0; i < errors.length; i++)
console.error(stripAnsi(errors[i]));
if(initial) return initial = false;
reloadApp();
});

io.on("disconnect", function() {
console.error("[WDS] Disconnected!");
});
var hot = false;
var initial = true;
var currentHash = "";

function reloadApp() {
if(hot) {
Expand Down
149 changes: 87 additions & 62 deletions client/live.js
Original file line number Diff line number Diff line change
@@ -1,83 +1,108 @@
var $ = require("jquery");
var io = require("socket.io-client");
var SockJS = require("sockjs-client");
var stripAnsi = require('strip-ansi');
require("./style.css");

var recInterval = null;
var sock = null;
var hot = false;
var currentHash = "";

var newConnection = function(handlers) {
sock = new SockJS('/sockjs-node');

clearInterval(recInterval);

sock.onclose = function() {
handlers.close();

// Try to reconnect.
sock = null;
recInterval = setInterval(function () {
newConnection(handlers);
}, 2000);
};

sock.onopen = function() {
// This callback also fires on a reconnect.
handlers.ok();
};

sock.onmessage = function(e) {
// This assumes that all data sent via the websocket is JSON.
var msg = JSON.parse(e.data);
handlers[msg.type](msg.data);
};
};

$(function() {
var body = $("body").html(require("./page.jade")());
var status = $("#status");
var okness = $("#okness");
var $errors = $("#errors");
var iframe = $("#iframe");
var header = $(".header");
var hot = false;
var currentHash = "";

var contentPage = window.location.pathname.substr("/webpack-dev-server".length) + window.location.search;

status.text("Connecting to socket.io server...");
status.text("Connecting to sockjs server...");
$errors.hide(); iframe.hide();
header.css({borderColor: "#96b5b4"});
io = io.connect();

io.on("hot", function() {
hot = true;
iframe.attr("src", contentPage + window.location.hash);
});

io.on("invalid", function() {
okness.text("");
status.text("App updated. Recompiling...");
header.css({borderColor: "#96b5b4"});
$errors.hide(); if(!hot) iframe.hide();
});

io.on("hash", function(hash) {
currentHash = hash;
});

io.on("still-ok", function() {
okness.text("");
status.text("App ready.");
header.css({borderColor: ""});
$errors.hide(); if(!hot) iframe.show();
});

io.on("ok", function() {
okness.text("");
$errors.hide();
reloadApp();
});

io.on("warnings", function(warnings) {
okness.text("Warnings while compiling.");
$errors.hide();
reloadApp();
});

io.on("errors", function(errors) {
status.text("App updated with errors. No reload!");
okness.text("Errors while compiling.");
$errors.text("\n" + stripAnsi(errors.join("\n\n\n")) + "\n\n");
header.css({borderColor: "#ebcb8b"});
$errors.show(); iframe.hide();
});

io.on("proxy-error", function(errors) {
status.text("Could not proxy to content base target!");
okness.text("Proxy error.");
$errors.text("\n" + stripAnsi(errors.join("\n\n\n")) + "\n\n");
header.css({borderColor: "#ebcb8b"});
$errors.show(); iframe.hide();
});
var onSocketMsg = {
hot: function() {
hot = true;
iframe.attr("src", contentPage + window.location.hash);
},
invalid: function() {
okness.text("");
status.text("App updated. Recompiling...");
header.css({borderColor: "#96b5b4"});
$errors.hide(); if(!hot) iframe.hide();
},
hash: function(hash) {
currentHash = hash;
},
"still-ok": function() {
okness.text("");
status.text("App ready.");
header.css({borderColor: ""});
$errors.hide(); if(!hot) iframe.show();
},
ok: function() {
okness.text("");
$errors.hide();
reloadApp();
},
warnings: function(warnings) {
okness.text("Warnings while compiling.");
$errors.hide();
reloadApp();
},
errors: function(errors) {
status.text("App updated with errors. No reload!");
okness.text("Errors while compiling.");
$errors.text("\n" + stripAnsi(errors.join("\n\n\n")) + "\n\n");
header.css({borderColor: "#ebcb8b"});
$errors.show(); iframe.hide();
},
"proxy-error": function(errors) {
status.text("Could not proxy to content base target!");
okness.text("Proxy error.");
$errors.text("\n" + stripAnsi(errors.join("\n\n\n")) + "\n\n");
header.css({borderColor: "#ebcb8b"});
$errors.show(); iframe.hide();
},
close: function() {
status.text("");
okness.text("Disconnected.");
$errors.text("\n\n\n Lost connection to webpack-dev-server.\n Please restart the server to reestablish connection...\n\n\n\n");
header.css({borderColor: "#ebcb8b"});
$errors.show(); iframe.hide();
}
};

io.on("disconnect", function() {
status.text("");
okness.text("Disconnected.");
$errors.text("\n\n\n Lost connection to webpack-dev-server.\n Please restart the server to reestablish connection...\n\n\n\n");
header.css({borderColor: "#ebcb8b"});
$errors.show(); iframe.hide();
});
newConnection(onSocketMsg);

iframe.load(function() {
status.text("App ready.");
Expand Down
54 changes: 35 additions & 19 deletions lib/Server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ var path = require("path");
var webpackDevMiddleware = require("webpack-dev-middleware");
var express = require("express");
var compress = require("compression");
var socketio = require("socket.io");
var sockjs = require("sockjs");
var StreamCache = require("stream-cache");
var http = require("http");
var https = require("https");
Expand All @@ -23,15 +23,20 @@ function Server(compiler, options) {
this.hot = options.hot;
this.headers = options.headers;

this.sockWrite = function(type, data) {
this.sock.write(JSON.stringify({type: type, data: data}));
}

// Listening for events
var invalidPlugin = function() {
if(this.io) this.io.sockets.emit("invalid");
if(this.sock) this.sockWrite("invalid");
}.bind(this);
compiler.plugin("compile", invalidPlugin);
compiler.plugin("invalid", invalidPlugin);
compiler.plugin("done", function(stats) {
if(!this.io) return;
this._sendStats(this.io.sockets, stats.toJson());
if(!this.sock) return;

this._sendStats(stats.toJson());
this._stats = stats;
}.bind(this));

Expand Down Expand Up @@ -146,7 +151,7 @@ function Server(compiler, options) {
}
proxy.web(req, res, proxyOptions, function(err){
var msg = "cannot proxy to " + proxyOptions.target + " (" + err.message + ")";
this.io.sockets.emit("proxy-error", [msg]);
this.sockWrite("proxy-error", [msg]);
res.statusCode = 502;
res.end();
}.bind(this));
Expand Down Expand Up @@ -177,7 +182,7 @@ function Server(compiler, options) {
app.all("*", function(req, res) {
proxy.web(req, res, contentBase, function(err) {
var msg = "cannot proxy to " + contentBase.target + " (" + err.message + ")";
this.io.sockets.emit("proxy-error", [msg]);
this.sockWrite("proxy-error", [msg]);
res.statusCode = 502;
res.end();
}.bind(this));
Expand Down Expand Up @@ -264,21 +269,32 @@ Server.prototype.setContentHeaders = function(req, res, next) {
next();
}

// delegate listen call and init socket.io
// delegate listen call and init sockjs
Server.prototype.listen = function() {
this.listeningApp.listen.apply(this.listeningApp, arguments);
this.io = socketio.listen(this.listeningApp, {
"log level": 1
var sockServer = sockjs.createServer({
// Limit useless logs
log: function(severity, line) {
if (severity === 'error') {
console.log(line);
}
}
});
this.io.sockets.on("connection", function(socket) {
if(this.hot) socket.emit("hot");
sockServer.on("connection", function(conn) {
this.sock = conn;
if(this.hot) this.sockWrite("hot");
if(!this._stats) return;
this._sendStats(socket, this._stats.toJson(), true);
this._sendStats(this._stats.toJson(), true);
}.bind(this));

sockServer.installHandlers(this.listeningApp, {
prefix: '/sockjs-node'
});
}

Server.prototype.close = function() {
this.io.close(); // Will also close listeningApp
this.sock.close(); // Will also close listeningApp
this.sock = null;
this.middleware.close();
}

Expand All @@ -297,17 +313,17 @@ Server.prototype.serveMagicHtml = function(req, res, next) {
}

// send stats to a socket or multiple sockets
Server.prototype._sendStats = function(socket, stats, force) {
Server.prototype._sendStats = function(stats, force) {
if(!force && stats && (!stats.errors || stats.errors.length === 0) && stats.assets && stats.assets.every(function(asset) {
return !asset.emitted;
})) return socket.emit("still-ok");
socket.emit("hash", stats.hash);
})) return this.sockWrite("still-ok");
this.sockWrite("hash", stats.hash);
if(stats.errors.length > 0)
socket.emit("errors", stats.errors);
this.sockWrite("errors", stats.errors);
else if(stats.warnings.length > 0)
socket.emit("warnings", stats.warnings);
this.sockWrite("warnings", stats.warnings);
else
socket.emit("ok");
this.sockWrite("ok");
}

Server.prototype.invalidate = function() {
Expand Down
Loading

0 comments on commit 7dcd41d

Please sign in to comment.