How to

Sending real-time notifications with Socket.io in Node.js

TLDR; Websockets are a great way to create open communication between the client and the server. Great examples are Chat, Bidding System, Notifications, etc...

Nevo David
Nevo DavidJuly 18, 2022

How do websites work?

  • A user provides a URL to the web browser.
  • The browser sends a request to the web server, asking for resources related to the URL.
  • The server receives the request and sends an HTTP response containing the related files to the web browser.
  • The browser displays the response as web pages to the user.

This type of communication is an HTTP connection, suitable for applications where data doesn’t change frequently.

Have you ever used a forex trading app or visited a sports betting website? You will notice that the data changes almost every minute; these changes are possible with the help of WebSockets.

WebSockets create a connection between a client and a server, allowing them to send data both ways; client-server and server-client. Compared to HTTP, WebSockets provide a lasting bi-directional client-server connection, making it possible for data to change in real-time without refreshing the page.

Novu

If you want to implement in-app notifications (kind of like Facebook / Instagram / Upwork etc..), Check out Novu. We bring you the whole solution without dealing with WebSockets / scaling / databases / servers. Come and star us ⭐️🤩
https://github.com/novuhq/novu

Image description

And we are back!

Node.js has a built-in WebSocket module, but this module doesn’t provide the functionalities required to build complex real-time applications; this is why Socket.io exists.

Socket.io is a popular JavaScript library that allows us to create real-time, bi-directional communication between clients and a Node.js server. It is a highly performant and reliable library optimized to process a large volume of data messages with minimal delay. It follows the WebSocket protocol and provides better functionalities, such as fallback to HTTP long-polling or automatic reconnection, which enables us to build efficient chat and real-time web applications.

In this article, you’ll learn how to send notifications between web clients and a Node.js server using Socket.io. Before we start coding this project, let’s see how Socket.io works.

This tutorial assumes that you have a basic knowledge of building web applications with Express.js and Node.js.

How does the Socket.io library work?

Real-time Node.js applications such as forex trading, sports betting websites, chat applications, and many others use Socket.io. In this section, you’ll learn how Socket.io transfer messages between the client and the server in a web application.

The Socket.io library has two parts – the client and the server API. The client API enables users to connect to the server via WebSocket, and the server API initiates a Socket.io connection on the backend server.

To connect Socket.io to the web client, you’ll need to download the client JavaScript bundle via CDN or NPM.

For HTML clients, add this code within the head tag.

1<script src="https://cdn.socket.io/4.5.0/socket.io.min.js" integrity="sha384-7EyYLQZgWBi67fBtVxw60/OWl1kjsfrPFcaU0pp0nAh+i8FD068QogUvg85Ewy1k" crossorigin="anonymous"></script>

The code snippet above downloads Socket.io via CDN and exposes a client bundle at /socket.io/socket.io.js to the client. We can then access Socket.io by adding the code below to the bottom of our HTML body tag.

1<script src="/socket.io/socket.io.js"></script>
2<script>
3    const socket = io();
4</script>

For React.js, Next.js, and other JavaScript libraries or frameworks, you can download the Socket.io client API via NPM.

1npm install socket.io-client

For the backend server installation, you need to have at least Node.js v10 installed on your computer before you can install the Server API via NPM.

1npm install socket.io

With this library, you can create a Socket.io connection, connect web clients to the backend server, and start sending messages between the client and the server.
However, this is just a simple explanation of how Socket.io works. In this article, I will walk you through adding the Socket.io library to the client and the server by building a notification system.

Setting up Express.js on a Node.js server

Here, I will guide you through setting up Express.js on a Node.js server. Express.js is a fast, minimalist framework that provides several features for building Node.js web applications. It enables us to create the web client for Node.js applications.

Create a folder that will contain our app. Then, create a package.json file by running the code below.

1mkdir <folder-name>
2cd <folder-name>
3npm init -y

Create an index.js file – the entry point to the web application.

1touch index.js

Install Express.js, Nodemon, and Socket.io. Nodemon is a Node.js tool that automatically restarts the server after detecting file changes.

1npm install express nodemon socket.io

Configure Nodemon by adding the start command to the list of the scripts in the package.json file. The code snippet below starts the server using Nodemon.

1{
2  "name": "server",
3  "version": "1.0.0",
4  "description": "",
5  "main": "index.js",
6  "scripts": {
7    "test": "echo \"Error: no test specified\" && exit 1",
8    "start": "nodemon index.js" //npm start - starts the server with Nodemon
9  },
10  "author": "",
11  "license": "ISC",
12  "dependencies": {
13    "express": "^4.18.1",
14    "nodemon": "^2.0.19",
15    "socket.io": "^4.5.1"
16  }
17}

Update the index.js file to render an HTML page. Copy the code below into the index.js file.

1const express = require('express');
2const app = express();
3const path = require('path');
4const PORT = process.env.PORT || 8080;
5
6//enables us to host static CSS & JS files.
7//The public folder contains the CSS & JS files.
8app.use(express.static('public'));
9
10//Route to the homepage of the application
11app.get('/', (req, res) => {
12  res.sendFile(path.join(__dirname, '/index.html'));
13});
14
15//Listens for changes in the web application
16app.listen(PORT, () => {
17  console.log(`App listening at ${PORT}`);
18});

Create an index.html file that displays a message bar and button.

1<!DOCTYPE html>
2<html lang="en">
3  <head>
4    <meta charset="UTF-8" />
5    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
6    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7    <title>Socket IO Chat App</title>
8
9    <!-- Link to CSS file-->
10    <link rel="stylesheet" href="./index.css" />
11  </head>
12  <body>
13    <div id="message-bar">
14      <p id="notification"></p>
15    </div>
16    <form class="container">
17      <h2>Send Messages with Socket.io</h2>
18      <textarea
19        rows="5"
20        width="100%"
21        name="message"
22        id="message"
23        placeholder="Enter your message..."
24      ></textarea>
25      <button>SEND MESSAGE</button>
26    </form>
27  </body>
28</html>

Create a folder named public. This folder will contain the CSS file for the HTML page.

1mkdir public
2cd public
3touch index.css

Copy the code below into the index.css file

1* {
2  box-sizing: border-box;
3  margin: 0;
4  padding: 0;
5  font-family: 'Poppins', sans-serif;
6}
7#message-bar {
8  width: 100%;
9  display: flex;
10  align-items: center;
11  justify-content: center;
12}
13#notification {
14  color: #fff;
15}
16.container {
17  height: 80vh;
18  width: 100%;
19  padding: 20px;
20  display: flex;
21  flex-direction: column;
22  justify-content: center;
23}
24h2 {
25  text-align: center;
26  margin-bottom: 30px;
27}
28textarea {
29  font-size: 16px;
30  margin-bottom: 30px;
31  padding: 15px;
32  outline: none;
33}
34button {
35  width: 200px;
36  padding: 15px;
37  cursor: pointer;
38  background-color: #2c3639;
39  outline: none;
40  border: none;
41  color: #dcd7c9;
42  font-size: 16px;
43}
44button:hover {
45  background-color: #3f4e4f;
46}

Run the Node.js server. You can view the index.html file at https://localhost:8080 in your web browser.

1npm start

Configuring Socket.io on the client

In this section, I will walk you through connecting the web client to Socket.io.

Update the index.html file to connect Socket.io JavaScript bundles via CDN. Add the first snippet within the head tag and the other at the bottom of the body tag.

1<head>
2    <!-- This links to Socket.io client JavaScript bundle via CDN. -->
3    <script
4      src="https://cdn.socket.io/4.5.0/socket.io.min.js"
5      integrity="sha384-7EyYLQZgWBi67fBtVxw60/OWl1kjsfrPFcaU0pp0nAh+i8FD068QogUvg85Ewy1k"
6      crossorigin="anonymous"
7    ></script>
8  </head>
1<body>
2......
3The page content
4.....
5    <!-- Link to the JavaScript file-->
6    <script src="./script.js" type="module"></script>
7
8    <!-- This access the client JavaScript bundle provided via its CDN -->
9    <script src="/socket.io/socket.io.js"></script>
10  </body>

Create a JavaScript file – script.js that enables us to access the user’s inputs and the HTML elements on the webpage via JavaScript DOM.

1cd public
2touch script.js

Access the HTML elements via the Document Object Model provided by JavaScript.

1//In script.js
2
3const notify = document.querySelector('#notification');
4const message = document.querySelector('#message');
5const button = document.querySelector('button');
6const messageBar = document.querySelector('#message-bar');

Create an event listener that logs the message provided by the user to the console whenever the form is submitted.

1function printMessage(e) {
2  e.preventDefault();
3  console.log(message.value);
4}
5button.addEventListener('click', printMessage);

Next, add Socket.io to the client JavaScript file – script.js.

1const socket = io();
2
3socket.on('response', (data) => {
4  notify.textContent = data;
5  messageBar.style.backgroundColor = '#3F4E4F';
6  messageBar.style.height = '20vh';
7});

The code snippet above listens for messages labeled response from the server. If there is a message, it displays the message on the webpage.

Edit the printMessage function to send messages from the client to the Node.js server. The code snippet below sends messages to the server when a user clicks the submit button.

1function printMessage(e) {
2  e.preventDefault();
3  socket.emit('message', message.value);
4}

Adding Socket.io to the Node.js server

In this section, you will learn how to configure Socket.io on a Node.js server, and you can receive and send messages from the client via Socket.io.

Update the index.js by importing Socket.io and the HTTP module from Node.js. The HTTP module creates an HTTP server that allows Node.js to transfer data via the network.

1const express = require('express');
2const app = express();
3const path = require('path');
4const PORT = process.env.PORT || 8080;
5
6//New imports
7const http = require('http').Server(app);
8//Pass the Express app into the HTTP module.
9const socketIO = require('socket.io')(http);
10
11app.use(express.static('public'));
12
13app.get('/', (req, res) => {
14  res.sendFile(path.join(__dirname, '/index.html'));
15});
16
17//Listen for changes on the HTTP server not the Express server
18http.listen(PORT, () => {
19  console.log(`App listening at ${PORT}`);
20});

From the code snippet above, the HTTP server accepts the Express app as a parameter, and we listen for changes on the HTTP server instead of Express.

Before the app.get() block, create a connection to the web client with Socket.io.

1socketIO.on('connection', (socket) => {
2  console.log(`⚡: ${socket.id} user just connected`);
3  socket.on('disconnect', () => {
4    console.log('A user disconnected');
5  });
6});

The socket.io("connection") the function above creates a connection with the web client. Socket.io creates a unique ID for each client and logs the ID to the console whenever a user visits the web page. When you refresh or close the web page, the socket fires the disconnect event showing that a user has disconnected from the socket.

Next, update the function to send and receive data from the client.

1socketIO.on('connection', (socket) => {
2  console.log(`⚡: ${socket.id} user just connected`);
3  socket.on('disconnect', () => {
4    console.log('A user disconnected');
5  });
6
7  socket.on('message', (data) => {
8        //sends the data to everyone except you.
9    socket.broadcast.emit('response', data); 
10
11        //sends the data to everyone connected to the server
12    // socket.emit("response", data)
13  });
14});

*socket.broadcast.emit() – sends the data to everyone except you, and the socket.emit() – sends the data to everyone connected to the server, including you*

Congratulations!🎊 You’ve just completed the project for this tutorial.

Conclusion

In this tutorial, you’ve learned

  • What WebSockets are
  • Why and when do we need Socket.io?
  • How to connect Socket.io to a web client and a Node.js server, and
  • how to send messages between an HTML client and a Node.js server.

Socket.io supports private messaging and group chats, identifying users by nicknames, showing whether a user is online, and knowing if a user is typing.

With these features provided by Socket.io, you can build complex real-time applications useful in various industries such as aviation, gaming, media, and finance.

Socket.io is an excellent choice for real-time communication between a client and a Node.js server. Some other libraries like TwilioFirebaseSupabase, and many others support real-time communication. Feel free to check them out.

Thank you for reading,
You can find the full source code here:
https://github.com/novuhq/blog/tree/main/sending%20emails%20via%20SocketIO

Nevo David
Nevo DavidJuly 18, 2022

Related Posts

How to

Building an Investor List App with Novu and Supabase

Building an Investor List App with Novu and Supabase

Prosper Otemuyiwa
Prosper OtemuyiwaMarch 15, 2024
How to

Implementing Internationalization in Apps: How to Translate Notifications

Implementing Internationalization in Apps: How to Translate Notifications

Prosper Otemuyiwa
Prosper OtemuyiwaMarch 1, 2024
How to

🔥 Building an email automation system with React Flow and Resend 🎉

Creating an email automation system to message people with a sequence of messages every 10 minutes.

Nevo David
Nevo DavidJuly 31, 2023