TUTORIALS

How to Build a Chat App with WebSockets and Node.js

Chimezie Enyinnaya

View GitHub Repo
March 10, 2021

WebSockets enable seamless two-way communication between a client and server. In other words they allow websites to send and receive data in real time. Developers can use WebSockets to build chat applications, multiplayer games, or user interfaces which expose events in real-time, and much more.

In this tutorial, we'll be building a simple chat app that allows users to talk to each other. If you are looking for a more advanced solution be sure to checkout CometChat. Our real time messaging product is free to use, fast, scalable, feature complete and easy add to your existing product with our SDKs.

Prerequisites

Before following this tutorial, you need the following:

Dependencies

  • Express: a lightweight and flexible Node.js framework that provides robust set of features for building web applications.
  • Socket.IO: enables real-time bidirectional event-based communication. Socket abstract WebSocket connections. It uses WebSockets for transportation and automatically falls back to long polling if Websockets aren’t supported by the client.
  • Moment: helps you manipulate and format dates in JavaScript.
  • Nodemon: a tool that helps develop Node.js applications by automatically restarting the node application when file changes in the directory are detected.

Check out the demo, or dive straight into the code, it's on GitHub.

Setting up Express Server

Let's create the project directory and initialize the node project.

After running this command in your terminal:

mkdir webcage && cd webcage && npm init --y

You should have something like this:

As you can see, a basic package.json file has been created for you.

Next, we need to install the required dependencies using the command:

npm install express moment socket.io

Finally, install Nodemon as a dev dependency with the command:

npm install -D nodemon

Now that the dependencies are installed, we need to tell node how to run our server.

Replace the properties of the scripts object with the code:

And create an index.js file in the root directory with the code below. This will be the entry point for our app.

Now you can run the server with this command:

npm run dev

You should get something like this:

Perfect! We have successfully set up the Express server.

Serving Static Assets

Let’s set up our server to serve static assets including: HTML, CSS and JavaScript files. To do this, modify index.js to contain the content below:

This specifies that we want to serve static assets from the public sub-directory. You can create this directory with the command:

mkdir public

Inside the public directory, create an index.html file with the following content:

This will serve as the homepage/login screen for our chat application. Users will have to provide an email address, username, and a room/channel they want to join before they can chat with other people.

You can copy the content of the referenced style.css file from the GitHub repo. This should be stored in a directory named public/css

Now when you open http://localhost:3000 in your browser, you should see the login page below:

Setting up Socket.IO on the Server

Replace existing code in index.js with this:

Let's break down the moving parts of the codebase.

Firstly, we create an Express server then use it to initialize a socket.io server.

With the socket.io server instance initialized, we can emit and listen to events between the server and client.

We started by listening to a joinRoom event from the client. This event handles the following:

  • Send a message to the user they connect
  • Send a message that a new user has joined the room
  • Emit an event with the current users in a room

In the section of code below, the server listens for messages from the client and sends them to other users in the room.

When a client exits a room, the code below will remove the current user and update the list of active users.

You will notice we are using some helper functions in our code. Let's go ahead and add them now. In the root of your project, create a helper directory, and create these two files formatDate.js and userHelper.js.

The formatMessage function takes the username and message as arguments, and returns an object containing a formatted time, username, and message. Just like this:

The userHelper.js module handles user behavior.

At this point, we have successfully setup the server using socket.io

Handling Socket.IO on the Client

Now, let’s move to the frontend. Within the public directory, create a chat.html file with the following content:

In this snippet, we made the following changes:

  • Added an id of leave-btn for the Leave Room button. We will use this in our frontend code to prompt the user to confirm they are leaving a room
  • Included the client-side socket.io script.
  • Included the QS library via CDN. We will be using it to parse URL strings.
  • Included main.js. This will contain the code for our client application.

Inside the public directory, create a js directory with a main.js file with the following code:

Firstly, we use the DOM to target HTML the elements which will be updated. Then, we use the QS library to parse username and room from the URL.

For example: http://localhost:3000/chat.html?email=samueldoe%40example.com&username=Samuel&room=Business will result in

Next, we initialized the client-side socket.io connection and emit the joinRoom event to the server. Earlier, we saw how the server listened and handled this event.

In order to handle events sent by the server, we need to add these lines of code:

Remember, the server emits the roomUsers event, which contains the current users in a room and the room name. In our frontend code, we listen to this event and use the DOM to update the room name and active users list. We will handle the outputRoomName(name) and outputUsers(users) functions later.

Add these line of code:

The server emits a message event with "Messages are limited to this room!" as the payload.

In the frontend, we listen for this event and update the UI with the payload. We'll handle the outputMessage(message) soon.

The chatMessages.scrollTop = chatMessages.scrollHeight triggers the page to scroll to the latest message.

To enable users to send a message, add the following code:

Here, we add a submit event listener and prevent the default behavior with e.preventDefault(). Next, we select the text entered in the message box by the user and remove any whitespace from the beginning or end of the string. If the message doesn’t contain any text the function returns false. On the other hand, if the user has entered a message, emit the chatMessage event and send the message as to the server. Finally, clear the message box.

Add these lines of code:

This function is responsible for displaying new messages in the chat window. The message argument receives an object with the message, time and username which is then added to the main chat window.

The outputRoomName function displays the name of the room the user has joined.

The outputUsers function displays the current users in the room.

The users argument is an array of objects containing the id, room, and username of a user. When logged it to the console, you get this

Finally, the code below confirms the user wants to leave a room:

Congratulations !Now, when you restart your dev server and navigate to http://localhost:3000 in two different browser windows. You should see something like this:


Conclusion

In this tutorial, we briefly discussed WebSockets and the types of applications you can create using the protocol. We also built a simple chat app with Node.js and Socket.IO.

If you want to add chat to your application you should consider CometChat. Our fully featured platform includes real time chat, online presence notifications, typing and read notifications as well as rich media attachments and message history. We offer a range of SDKs making it easy to use with your existing technology stack.

About Author

Chimezie Enyinnaya is a software developer and instructor with passion for teaching and sharing his knowledge. You can learn more about him here: https://adonismastery.com and https://twitter.com/ammezie.

Related Posts

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

Try Us for Free 

For as Long as You Like!