95

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?

6
  • You dont' have to put the import in ./bin/www.. Just put it to the same place, where your var app is. Commented Jul 7, 2014 at 11:59
  • 17
    I wish people would stop suggesting express-io. It's outdated and no longer maintained. Commented Jul 7, 2014 at 12:01
  • @Mritunjay thank you, but it didn't solve it :/ Commented Jul 7, 2014 at 12:01
  • @BenFortune sorry I'll keep that in mind. Commented Jul 7, 2014 at 12:03
  • @alandarev var app = express() ?? I acctually tried it, no success Commented Jul 7, 2014 at 12:05

8 Answers 8

168

Here is how you can add Socket.io to a newly generated Express-Generator application:

  1. Create a file that will contain your socket.io logic, for example socketapi.js:

socketapi.js:

const io = require( "socket.io" )(); const socketapi = { io: io }; // Add your socket.io logic here! io.on( "connection", function( socket ) { console.log( "A user connected" ); }); // end of socket.io logic module.exports = socketapi; 
  1. Modify your bin/www launcher. There are two steps: requiring your Socket.io api and attaching the HTTP server to your socket.io instance right after creating the HTTP server:

bin/www:

/** * Module dependencies. */ var app = require('../app'); var debug = require('debug')('socketexpress:server'); var http = require('http'); let socketapi = require("../socketapi"); // <== Add this line /** * Get port from environment and store in Express. */ var port = normalizePort(process.env.PORT || '3000'); app.set('port', port); /** * Create HTTP server. */ var server = http.createServer(app); socketapi.io.attach(server); // <== Also add this line (...) 
  1. Then you just need to add the Socket.io client in your index.html. Add the following just before the </body> closing tag:

index.html

 (...) <script src="/socket.io/socket.io.js"></script> <script> var socket = io(); </script> </body> </html> 
  1. Finally you can start your Express server:
  • Unix based: DEBUG=myapp:* npm start
  • Windows: set DEBUG=myapp:* & npm start

Note 1

If for any reason you need access to your socket api in your app.js, then you could instead import your socket api in app.js, and re-export it:

app.js

var express = require('express'); var socketapi = require("./socketapi"); // <== Add this line (...) // You can now access socket.io through the socketapi.io object (...) module.exports = { app, socketapi }; // <== Export your app and re-export your socket API here 

Then in your bin/www launcher, instead of importing your socket api on its own line, just import it along your app:

bin/www

var {app, socketapi} = require('../app'); // <== Import your app and socket api like this (...) var server = http.createServer(app); socketapi.io.attach(server); // <== You still have to attach your HTTP server to your socket.io instance 

Note 2 This answer was updated to work with the latest Express Generator (4.16 at time of writing) and latest Socket.io (3.0.5 at time of writing).

Sign up to request clarification or add additional context in comments.

6 Comments

It is simply a matter of puting the io variable into the app object. It could also be : app.io = socket_io();
"... and even make it available to your routes if you want." Okay, but how? It would be great if you could give an example on how to do it.
@GabrielHautclocq how would I access this from my route? appreciate it!
Isn't it bad to attach a custom property to the app object? Better use symbols or app.set().
Why app.io = io when you could use module.exports = { app, io } instead
|
65

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.

5 Comments

This answer deserves more upvotes! Very simple and clean, it keeps socket routes outside www, app.js and also outside index.js (yes, outside index.js), this file should only contain Express HTTP routes.
Amazing, very clean
Can anyone update this for socket.io 2.0? It's not working for me. io.attach(server) and io.listen(server) both throw "cannot read property X of undefined".
Also to speak to @tsujp mine works the same. You have to hit the right url and add the socket.io client and you'll see it work
I have a similar problem as @tsujp, I'm using socket.io 2.3.0 and I'm getting io.attach is not a function
44

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

1 Comment

The problem is, you can't do something like io.on('connection', function(socket) { res.render('connection.jade') });
19

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".

Comments

9

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'); 

Comments

7

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!'); }); 

Comments

6

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

Comments

2

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.