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


So here is the deal: I'm trying to use socket.io in an express project. After Express Js 4 was lauched, i've updated my express-generator and now the app initial functions goes into ./bin/www file, including those vars (www file contents: http://jsfiddle.net/avMa5/ )

var server = app.listen(app.get('port'), function() {..}

(check it by npm install -g express-generator and then express myApp

that being said, let's remember how socket.io docs ask us to fire it:

var app = require('express').createServer();
var io = require('socket.io')(app);

Ok but i can't do it inside app.js, like recommended. This should be done in ./bin/www in order to work. in ./bin/www this is what i can do to get it working:

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

Ok this works, but i can't use the io var anywhere else, and i really don't want to put my socket.io functions on www file.

I guess this is just basic syntax, but I can't get this to work, not even using module.exports = server or server.exports = server nor module.exports.io = app(io) on www file

So the question is: how can i use socket.io having this /bin/www file as starting point of my app?

A little different approach to initiate socket.io, it groups all related code in one place:

bin/www

/**
 * Socket.io
 */
var socketApi = require('../socketApi');
var io = socketApi.io;
io.attach(server);

socketApi.js

var socket_io = require('socket.io');
var io = socket_io();
var socketApi = {};

socketApi.io = io;

io.on('connection', function(socket){
    console.log('A user connected');
});

socketApi.sendNotification = function() {
    io.sockets.emit('hello', {msg: 'Hello World!'});
}

module.exports = socketApi;

app.js

// Nothing here

In this way all socket.io related code in one module and function from it I can invoke from anywhere in application.


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


The old "expressjs", everything is happening in the file "app.js". So the socket.io binding to server also happens in that file. (BTW, one can still do it the old way, and remove bin/www)

Now with the new expressjs, it needs to happen in the "bin/www" file.

Fortunately, javascript/requirejs made it easy to pass objects around. As Gabriel Hautclocq pointed out, socket.io is still "imported" in "app.js" and it gets attached to "app" object via a property

app.io = require('socket.io')();

The socket.io is made live by attaching to it the server in "bin/www"

app.io.attach(server); 

because "app" object is passed into "bin/www" earlier

app = require("../app");

It's really just as simple as

require('socket.io')().attach(server);

But doing it the "difficult" way ensures that app.io now holds the socke.io object.

Now if you need this socket.io object also in "routes/index.js" for example, just use the same principle to pass that object around.

First in "app.js", do

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

Then in "routes/index.js"

module.exports = function(io){
    //now you can use io.emit() in this file

    var router = express.Router();



    return router;
 }

So "io" gets injected into "index.js".


Update to Gabriel Hautclocq's response:

In www file, the code should appear as the following due to updates with Socket.io. Attach is now Listen.

/**
 * Create HTTP server.
 */

var server = http.createServer(app);

/**
 * Listen on provided port, on all network interfaces.
 */

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);


/**
 * Socket.io
 */
var io = app.io;
io.listen(server);`

Additionally getting that connection to work requires implementing the client side API as well. This isn't Express specific but without it the connect call won't work. The API is included in

/node_modules/socket.io-client/socket.io.js. 

Include this file on the front end and test with the following:

var socket = io.connect('http://localhost:3000');

A tutorial for beginners from Cedric Pabst
here are the short basics form the link for an app chat:

using express-generate and the ejs engine usable in every .ejs file standard routing in express-generate

edit the file bin\www and add this app.io.attach(server); like this

...
/*
 * Create HTTP server.
/*  
var server = http.createServer(app);
/*
 * attach socket.io
/*  
app.io.attach(server); 
/*
 * Listen to provided port, on all network interfaces.
/*  
...

edit in app.js

//connect socket.io
... var app = express();
// call socket.io to the app
app.io = require('socket.io')();

//view engine setup
app.set('views', path.join(_dirname, 'views'));
...



...
//start listen with socket.io
app.io.on('connection', function(socket){
console.log('a user connected');

// receive from client (index.ejs) with socket.on
socket.on('new message', function(msg){
      console.log('new message: ' + msg);
      // send to client (index.ejs) with app.io.emit
      // here it reacts direct after receiving a message from the client
      app.io.emit('chat message' , msg);
      });
});
...
module.exports = app;

edit in index.ejs

 <head>  
   <title><%= title %></title>
   <link rel='stylesheet' href='/stylesheets/style.css' />
   <script src="/socket.io/socket.io.js"></script>
   //include jquery
   <script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
   <script>
   var socket = io();
   //define functions socket.emit sending to server (app.js) and socket.on receiving 
     // 'new message' is for the id of the socket and $('#new-message') is for the button
     function sendFunction() {
     socket.emit('new message', $('#new-message').val());
     $('#new-message').val('');
   }
    // 'chat message' is for the id of the socket and $('#new-area') is for the text area
   socket.on('chat message', function(msg){
     $('#messages-area').append($('<li>').text(msg));
   });
   </script>
 </head>  

 <body>  
   <h1><%= title %></h1>
   <h3>Welcome to <%= title %></h3>
   <ul id="messages-area"></ul>
   <form id="form" onsubmit="return false;">
     <input id="new-message" type="text" /><button onclick="sendFunction()">Send</button>
   </form>
 </body>

Have fun :) and thanks many to Cedric Pabst


Some previous answers are not working and others are overly complicated. Try the following solution instead...

Install server-side and client-side socket.io node modules:

npm install --save socket.io socket.io-client

Server-side

Add the following code to bin/www after the server definition, var server = http.createServer(app);:

/**
 * Socket.io
 */

var io = require('socket.io')(server);

io.on("connection", function(socket){
  console.log("SOCKET SERVER CONNECTION");
  socket.emit('news', { hello: 'world' });
});

Client-side

If using webpack, add the following code to your webpack entry.js file:

var socket = require('socket.io-client')();
socket.on('connect', function(){
  console.log("SOCKET CLIENT CONNECT")
});

socket.on('news', function(data){
  console.log("SOCKET CLIENT NEWS", data)
});

Done. Visit your site and check the browser's js developer console.


I have a solution for making socket.io available in app.js.

app.js:

var express      = require( "express"   );
var socket_io    = require( "socket.io" );

// Express
var app          = express();

// Socket.io
var io           = socket_io();
app.io           = io;

(...)

// socket.io events
io.on( "connection", function( socket )
{
    console.log( "A user connected" );
});

module.exports = app;

// Or a shorter version of previous lines:
//
//    var app = require( "express"   )();
//    var io  = app.io = require( "socket.io" )();
//    io.on( "connection", function( socket ) {
//        console.log( "A user connected" );
//    });
//    module.exports = app;

bin/www:

(...)

/**
 * Create HTTP server.
 */

var server = http.createServer( app );


/**
 * Socket.io
 */

var io     = app.io
io.attach( server );

(...)

This way, you can access the io variable in your app.js, and even make it available to your routes by defining module.exports as a function which accepts io as a parameter.

index.js

module.exports = function(io) {
    var app = require('express');
    var router = app.Router();

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

    return router;
}

Then, pass io into the module after it is setup:

app.js

// Socket.io
var io = socket_io();
app.io = io;

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

After reading through all of the comments, I came up with the following using Socket.io Server Version: 1.5.0

Issues that I ran into:

  1. var sockIO = require('socket.io') should be var sockIO = require('socket.io')(). (Credit to: Zhe Hu)

  2. sockIO.attach should be sockIO.listen (Credit to: rickrizzo)

Steps

  1. Install Socket.io with the following command:

    npm install --save socket.io
    
  2. Add the following to app.js:

    var sockIO = require('socket.io')();
    app.sockIO = sockIO;
    
  3. In bin/www, after var server = http.createServer(app), add the following:

    var sockIO = app.sockIO;
    sockIO.listen(server);
    
  4. To test functionality, in app.js, you can add the line:

    sockIO.on('connection', function(socket){
        console.log('A client connection occurred!');
    });