How to Use Socket.io with Express

socket.io allows us to make a connection between a client and a server but have that connection persist.

Normally, the client and server would have a simple transaction: the client would get data from the server then close the connection. If the client needs 10 pieces of information they have to make 10 requests. With WebSockets, the client can connect to the server and have that connection stay open. So the client can make 10 requests with just 1 connection.

Socket.IO is composed of two parts:

  • A server that integrates with (or mounts on) the Node.JS HTTP Server
  • A client library that loads on the browser side

Set up Socket.io on Express Server

Install dependencies: The only packages you need are Express and Socket.io

npm install express socket.io

Import packages

const http = require('http');
const express = require('express');
const socketio = require('socket.io');

Create io object

const app = express();
const server = http.createServer(app);
const io = socketio(server);

http.createServer is used by Express under the hood but we need to access it directly

Socket.io Methods on the Server

This is a function that runs every time a client connects to our server. In the callback, we create a socket instance for each one of the clients

We can access the socket.id, a random ID that is automatically assigned to them when they join the server.

// Run when client connects
io.on('connection', socket => {
   console.log('New WS Connection...');
});

socket.on listens for events from the client

The string "sendMessage" is a custom event emitted from the client whenever a new message is sent. socket.on allows us to access that event and any data sent with it (message) on the server.

socket.on("sendMessage", message => {
   console.log(message)
})

io.emit sends an event down to every client connected to the server

In this example, we are taking the message that was sent to the server with "sendMessage" and emitting it to all the connected sockets through an event called "recieveMessage".

socket.on("sendMessage", message => {
   io.emit("recieveMessage", message)
})

In order to send a message to every socket except the socket sending the message, use socket.broadcast.emit

socket.broadcast.emit("recieveMessage", message)

Emit message to a room with socket.to in front of the emit command

socket.on("sendMessage", (message, room) => {
   socket.to(room).emit("receiveMessage", message)
})

To join a room, use the socket.join method. You can only join a room from the server, not the client.

socket.on("joinRoom", room => {
   socket.join(room)
})

Send a callback function to the server.

On the client, pass the callback function as the last parameter.

socket.emit("joinRoom", room, message => {
   displayMessage(message)
})

On the server, use the callback function. Basically, you’re doing this: displayMessage(`Joined ${room}`)

socket.on("joinRoom", (room, cb) => {
   socket.join(room)
   cb(`Joined ${room}`)
})

Disconnect from the server

socket.on('disconnect', () => {
   //...
});

Socket.io on the Client

In this tutorial, we are assuming you are using static HTML pages as the frontend. So no JavaScript frameworks like React or Vue.

If Socket.io is installed in the root directory, you can use the client library in our public files by simply adding this line to your main HTML file

<script src="/socket.io/socket.io.js"></script>

You can create a Socket object with this command:

const socket = io()

If Socket.io is NOT installed in the root directory, you must install the socket.io-client package in your client folder.

npm i socket.io-client

Then, in a JavaScript file you can import io from the library

import { io } from 'socket.io-client'

Then, create a socket on the frontend by calling the io function and passing in the address of the server.

const socket = io('http://localhost:3000')

Also, on the server, make sure you add the following parameters to the require('socket.io') function. This will prevent CORS from blocking the frontend from connecting to the backend. The URL should be the URL that your frontend application is running on.

const io = socketio(server, {
  cors: {
    origin: ['http://localhost:8080']
  }
});

Use socket.on to receive events from the server

// Receive message from server and output it to screen
socket.on('message', (message) => {
  outputMessage(message);
});

// Example 2
socket.on('roomUsers', ({ room, users }) => {
  outputRoomName(room);
  outputUsers(users);
});

Use socket.emit to send events to the server

// Tell server you want to join a chatroom
socket.emit('joinRoom', { username, room });

How to Build a Node.js Project for Beginners

First, make sure you have Node installed. I’m not going to show how to do that in those tutorial. For developers that already know how to use Node, this tutorial can serve as a guide to help jog your memory whenever you forget all the steps to building a new Node.js project.

Once you have Node installed, you can write these commands in Terminal to get started:

mkdir folder-name    (create a new folder)
npm init             (initialize Node Package Manager)
touch index.js       (create server file)

For the npm init step, it will make you click through a bunch of prompts/set-up questions to set up NPM in your folder.

For your server file, it doesn’t matter what it’s name is as long as you make sure it has the same name as the one you defined in the NPM initialization questions.

In Terminal within your project directory, add these NPM packages to your project using the command npm i or npm install

npm i express         (install express - a Node web framework)
npm i -D nodemon      (install nodemon as a dev dependency)

Open up your server file (index.js) in a code editor (I prefer Visual Studio Code) and type this Node code:

const express = require('express');

const app = express();

const PORT = process.env.PORT || 4000;

app.listen(PORT, console.log(`Server started on port ${PORT}`));

The Express framework is the most popular Node backend web framework by far and it will make working with Node for the web 100x easier.

To run this and make sure it works, type this command in your Terminal (make sure your in your project directory):

nodemon index.js

The Terminal should output the string “Server started on port 4000” (or port 5000, 6000, etc. based on what you put in your code).

This means that the project is running on the specified port on your localhost.