TUTORIALS

How to Build a Chat App with Socket.io & Node.js

Antonio Ufano

View GitHub Repo
February 16, 2021

Socket.io is a Javascript library for web apps that allows real-time communication between clients and servers. It's built on top of the Websockets API (client) and Node.js (server). If you want to learn what Websockets are, watch this super quick video to understand the basic concepts. The most common use cases for Websockets and socket.io are chat applications or a social media feeds in which a user's page (client) receives messages or posts from other users.

In this article, we'll build a simple chat application that allows users to talk to each other in real-time. Our application will consist of two separate components, a server, and a client, each one with different responsibilities:

Chat server responsibilities

  • Serve the HTML, CSS and JavaScript client files to the users
  • Start the Socket.io connection
  • Receive events from clients (like a new chat message) and broadcast them to other clients

Chat client responsibilities

  • Load socket.io client library from a CDN
  • Establish connection with the Socket.io running in our server
  • Ask the user to enter his name so we can identify him in the chat
  • Emit and receive events to/from Socket.io running in our server
  • Add our own messages to the chat via JavaScript

Now that we know what do we need to build, let's start coding!

Setting up the web server

Let's start by initialising our project running npm init. The first responsability we need to take care of is creating a web server that serves the HTML, CSS and JavaScript files to our clients. To do so, we'll use Node's integrated http module. We'll create a file named server.js and include the following code:

In summary, the code above starts a server that handles requests and serves files contained in a folder named client.

Now we go ahead and create a folder named client with an index.html file inside it with the following content:

Now run npm start and open http://localhost:3000 in your browser to see our index page.

Page loaded

Initializing Socket.io in the server and client

Our basic web server is working and serving HTML files (we'll take care of serving JavaScript and CSS files in a bit 😉) so now we can start working on our chat. Install socket.io by running npm i socket.io and then include the following lines into our server.js file:

Let's see what this code does:

  • Imports socket.io and attach it to our app server
  • With io.on('connection) we detect a new connection and log a message in the console including the socket object, which will contain some information from the client.

Now we have to modify our index.html document to load the socket.io library from a CDN and also load a chat.js file that we're going to create inside the client folder of our server:

In the chat.js file we will add all the code to emit and handle events for our chat. For now, it will just have the following code which connects the client to the Socket.io instance running on the host that served the page (our server):

If we test this, we'll see that the page loads both JavaScript files and in our server console we'll see the "👾 New socket connected!" message.

Client socket connected in server console

If we open multiple tabs/windows, we'll see multiple messages in our server console.

Creating the chat

Now that we have our Socket.io instance running in the server and our client (the page) connected to it, it's time to move on and start creating our chat

Storing the connected clients

Let's start by storing the information of each client connected to our server. To identify each client, we'll ask the users to enter their name in a promt and additionally, we'll save their socket id. Modify your chat.js file like this:

We're using the prompt() method to request the username. With socket.emit() we're emitting to our server. The first parameter is the event name and the second parameter is the data we're sending, in this case, just the username. Using socket.on() we capture events sent from the server to the clients.

In our server, we have to capture the event like this:

As you can see, we've added a users object in which we'll store all the users connected. To capture the event sent from the client, we use the socket.on() method which receives the data sent from the client, containing the username. After we save the user details we emit another event, this time from the server to the client with a welcome message.

Users stored

In summary, the most used functions when working with Socket.io are socket.emit(eventName, data) and socket.on(eventName, data) to emit and capture events in both the server and the clients. As a rule of thumb, just remember to have an socket.on() function for each event you send with socket.emit()

Handling chat messages

Now that we know how to emit and handle events in both the client and the server, we can start working on the events to send and receive chat messages. But first, we need to create the HTML input to enter the message to send and the container that will hold all the conversation's messages.

I'm including some styles to help us position all the elements and differentiate between our own and other user's messages on the chat. There is an empty container with id chatContainer in which we'll append any messages. At the bottom, there is a form with the input and button to send the messages.

Moving to our chat.js file, we'll create a helper function addMessage() to append messages to the chatContainer and invoke it right after we receive the welcome-message event from the server.

This function will receive a data object which will contain the username and the message itself, and a isSelf flag which indicates if the message is ours. We'll use this second parameter to choose a different style to display the message. This is how it'll look like:

Welcome message displayed on the chat

The next step is to send messages from a client and broadcast them to all the other clients. We'll have to add an event listener in our submit button and, as we've done before, use the socket.emit() function in the client to send the message to our server. We'll also add another event handler for broadcast-message which we'll emit from the server when other clients send a message:

As you can see, we're calling the addMessage function to append our own message to the chat container without involving our server.

Now in our server, we need to capture the new-message event using the socket.on() method and emit the broadcast-message event:

Notice that when the server receives the new-message event, now we're using socket.broadcast.emit() instead of just socket.emit(). The difference is that when broadcasting, we're sending an event to all clients except the one that sent the original event.

Give it a try and...

There are a couple of things we can do to improve this chat a little bit. For example, we can detect when a client disconnects and send a message to the remaining users. You can find that in the full code in this repository.

Conclusion

Socket.io is a super powerful library and we've just scratched some basic methods from its API but it contains a lot more functionalities like assigning namespaces to sockets so they have different endpoints, create rooms and, even integrate it with Redis. Make sure to check out their documentation to learn more.

I hope you find this article useful and it helps you create awesome projects using Socket.io.

About Author

Antonio is a full stack developer from Spain currently living in UK. He has more than 12 years of professional experience working on a wide variety of projects, from small personal websites to complex web applications or corporate projects built with microservices and REST APIs. Now he's working on my his projects: thelifeboard.app and quicktalks.io

Related Posts

No items found.
No items found.
No items found.

Try Us for Free 

For as Long as You Like!