Skip to content

Option for listening to unix socket #661

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 27, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 64 additions & 17 deletions bin/webpack-dev-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
var path = require("path");
var open = require("opn");
var fs = require("fs");
var net = require("net");
var url = require("url");

// Local version replaces global one
Expand Down Expand Up @@ -130,6 +131,11 @@ yargs.options({
default: 8080,
group: CONNECTION_GROUP
},
"socket": {
type: "String",
describe: "Socket to listen",
group: CONNECTION_GROUP
},
"public": {
type: "string",
describe: "The public hostname/ip address of the server",
Expand Down Expand Up @@ -172,6 +178,9 @@ function processOptions(wpOpt) {
if(argv.port !== 8080 || !options.port)
options.port = argv.port;

if(argv.socket)
options.socket = argv.socket;

if(!options.publicPath) {
options.publicPath = firstWpOpt.output && firstWpOpt.output.publicPath || "";
if(!/^(https?:)?\/\//.test(options.publicPath) && options.publicPath[0] !== "/")
Expand Down Expand Up @@ -299,27 +308,65 @@ function processOptions(wpOpt) {
}));
}

new Server(compiler, options).listen(options.port, options.host, function(err) {
if(err) throw err;
var uri = url.format({
protocol: protocol,
hostname: options.host,
pathname: options.inline !== false ? "/" : "webpack-dev-server/",
port: options.socket ? 0 : options.port.toString()
});

var uri = url.format({
protocol: protocol,
hostname: options.host,
port: options.port.toString(),
pathname: options.inline !== false ? "/" : "webpack-dev-server/"
var server = new Server(compiler, options);

if(options.socket) {
server.listeningApp.on("error", function(e) {
if(e.code === "EADDRINUSE") {
var clientSocket = new net.Socket();
clientSocket.on("error", function(e) {
if(e.code === "ECONNREFUSED") {
// No other server listening on this socket so it can be safely removed
fs.unlinkSync(options.socket);
server.listen(options.socket, options.host, function(err) {
if(err) throw err;
});
}
});
clientSocket.connect({ path: options.socket }, function() {
throw new Error("This socket is already used");
});
}
});
server.listen(options.socket, options.host, function(err) {
if(err) throw err;
var READ_WRITE = 438; // chmod 666 (rw rw rw)
fs.chmod(options.socket, READ_WRITE, function(err) {
if(err) throw err;
reportReadiness(uri, options);
});
});
} else {
server.listen(options.port, options.host, function(err) {
if(err) throw err;
reportReadiness(uri, options);
});
}
}

function reportReadiness(uri, options) {
if(options.socket) {
console.log("Listening to socket", options.socket);
} else {
console.log(" " + uri);
}

console.log("webpack result is served from " + options.publicPath);
if(Array.isArray(options.contentBase))
console.log("content is served from " + options.contentBase.join(", "));
else if(options.contentBase)
console.log("content is served from " + options.contentBase);
if(options.historyApiFallback)
console.log("404s will fallback to %s", options.historyApiFallback.index || "/index.html");
if(options.open)
open(uri);
});
console.log("webpack result is served from " + options.publicPath);
if(Array.isArray(options.contentBase))
console.log("content is served from " + options.contentBase.join(", "));
else if(options.contentBase)
console.log("content is served from " + options.contentBase);
if(options.historyApiFallback)
console.log("404s will fallback to %s", options.historyApiFallback.index || "/index.html");
if(options.open)
open(uri);
}

processOptions(wpOpt);
43 changes: 43 additions & 0 deletions examples/listen-socket/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Listen to socket

Start dev server in socket mode:

```shell
node ../../bin/webpack-dev-server.js --socket ./webpack.sock
```

And then start node server that will use that socket:

```shell
node check-socket.js
```

You should see this responses to this command:

```shell
Successfully connected to socket, exiting
```

Common use-case for this feature is configuring upstream in nginx that points to webpack socket.
Listening to socket instead of port is much more convenient because if you have many applications you don't have to resolve port conflicts since each of them has own unique socket.

Example of configuring upstream with Websockets support in nginx:

```
location /webpack/ {
proxy_pass http://unix:/home/happywebpackuser/apps/todo/webpack.sock;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://unix:/home/resure/code/statface-raw/app/run/statbox.sock;
proxy_redirect off;
}
location /sockjs-node/ {
proxy_pass http://unix:/home/happywebpackuser/apps/todo/webpack.sock;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
```

Replace `/webpack/` with your `publicPath` param value and path in `proxy_pass` to your actual proxy location.
1 change: 1 addition & 0 deletions examples/listen-socket/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
document.write("It's working.");
9 changes: 9 additions & 0 deletions examples/listen-socket/check-socket.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"use strict";

var net = require("net");

var client = net.createConnection("./webpack.sock");
client.on("connect", function() {
console.log("Successfully connected to socket, exiting");
process.exit(1); // eslint-disable-line
});
4 changes: 4 additions & 0 deletions examples/listen-socket/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
context: __dirname,
entry: "./app.js",
}