Using Socket.Io in Express 4 and Express-Generator's /Bin/Www

Using socket.io in Express 4 and express-generator's /bin/www

It turns out it really was some basic sintax problem.... I got these lines from this socket.io chat tutorial...

on ./bin/www, just after var server = app.listen(.....)

var io = require('socket.io').listen(server);
require('../sockets/base')(io);

so now I create the ../sockets/base.js file and put this little fellow inside it:

module.exports = function (io) { // io stuff here... io.on('conection..... }

Yeah! Now it works... So i guess i really had no option other than starting socket.io inside /bin/www , because that is where my http server was started.
The goal is that now i can build socket functionality in other file(s), keeping the thing modular, by require('fileHere')(io);

<3

Using socket.io with express 4 generator

I have to say, I think the default generated project is bad for a socket.io setup. The node http.Server var is all the way in bin/www and not in app.js.

So the first thing is to move all the relevant stuff from bin/www to app.js. Mainly you just need

var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);

just like in the socket.io docs.

Now with io in app.js, we can use that when the routes are required. I forgot how exactly the default routes are set up, but I think they set up an app and just export it. Instead, you can set up something like

module.exports = function(app, io) {
io.on('connection', function(socket) {
console.log('connected!');
}

app.get('/foo', function() {
...
}
}

And now when you require the routes, instead of having the default

var index = require('./routes/index');
app.use(index);

or something of that accord, you can just do

require('./routes/index')(app, io);

And that's how you get io into your routes. Or at least how I do it anyway.

Express-Generator - Including socket.io (bin/www)

Its typical to require socket.io in app.js and then to tell your io sever to listen to your application. Using the example you posted, that would look like this:

var debug   = require('debug')('rhubarb');
var app = require('../app');
var server = require('http').Server(app);
var io = require('socket.io')(server);

app.set('port', process.env.PORT || 1127);

var server = server.listen(app.get('port'), function() {
debug('Express server listening on port ' + server.address().port);
});

The socketio docs do a really good job of explaining this. Here's an example from their homepage:

var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);

server.listen(80);

app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});

io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});

Update:

I typically modularize socketio setup by creating a lib called io.js in /lib with something like this:

module.exports = function(server){
var io = require('socket.io')(server);

// catch errors
io.on('error', function(err){
throw err;
})

// Set Socket.io listeners by creating a socket.io middleware
// attachEventlisteners would live in `/controllers`
io.use(attachEventlisteners);

io.on('connection', function (socket) {

// do things

});

return io; // so it can be used in app.js ( if need be )
}

then in app.js i can simply pass the server in when I require it:

  var io = require('./lib/io')(server);

You dont need to do any thing further in app.js since everything is setup in /lib/io.js, but if you wanted to you could because the io server is returned.

Node.js Express 4 Generator with Mutliple Socket.io files

You're overwriting app.io each time. app.io = require('./socket.io/file1'); isn't "calling socket.io" but assigns app.io to that module. There are multiple ways to solve this, for example:

in app.js:

app.io = [
require('./socket.io/file1'),
require('./socket.io/file2'),
require('./socket.io/file3')
]

in /bin/www:

app.io.forEach(function (socketIo) {
socketIo.attach(server);
});

This assigns an array to app.io and /bin/www iterates over the array to attach the server to each socket.io instance.

I couldn't test if this works and i suspect it doesn't (I wrote it just to illustrate the first problem in your code). I think one can use only a single socket.io instance per http server. But there is a solution:

tl;dr

Use socket.io namespaces. Create a single instance of socket.io and attach it to the server like you already do, then create "submodules" via io.of("/module-name") in each of your module files (like file1, etc). Please read the documentation to learn more about namespaces.


Update:

There are again multiple options to do that, e.g.: (Warning, code is from one of my own codebases, and is originally written in coffee-script and translated in my head, but you should get the gist)

in io.coffee

var io = require('socket.io')(http)

require('./broadcast.coffee')(io)
require('./livelog.coffee')(io)

Where http is, of course, your http server instance.

in broadcast.coffee

module.exports = function (io) {
var broadcast = io.of('/broadcast')

broadcast.on('connection', function (socket) {
socket.emit('foo', 'bar')
})
}

socket.io with express generator

in app.js you have this code:

var messages = require('./routes/messages')(io);

var app = express();

// socket.io

var io = socket();
app.io = io;

You should initialize io variable before passing it to messages export function - like so:

var app = express();

// socket.io

var io = socket();
app.io = io;

var messages = require('./routes/messages')(io);

Socket.io and Express 4

For your first two questions, I believe this post will help you with that Using socket.io in Express 4 and express-generator's /bin/www

As for your last question, you should put the relevant socket.io logic within the file of where it's needed. It definitely should not all be stored in one place. In the chat example of socket.io, you'll notice that they separate the socket.io logic from when you send a message to when you receive one.

Configure socket.io with node express generator

First, let me tell you, what you're trying to do is kinda right. Not to mess with the bin/www would be fine.

But remember express generator is just that. A generator for you to build upon. You generate, and the apply your own modifications.

My choice would be to:

  • copy bin/www to a new bin/wwwio,
  • Update the bin/wwwio script to attach socket.io to the created http server.
  • Update bin/wwwio to require() a new file ../io.js that handles all my socket.io events.
  • Modifiy package.json to run node ./bin/wwwio on npm start instead of bin/www

You can also look at the answers on this other question about the some topic:

Using socket.io in Express 4 and express-generator's /bin/www

You'll find several approaches to achieving modularity with little touching on the bin/www script.



Related Topics



Leave a reply



Submit