Real-time Chatting and Shared Workspace App with Socket.io, NodeJS and ExpressJS
By: Aaron .L. Gomes
Tags: Nodejs, Real Time Chat, Chat, Socketio, Expressjs

Photo by Kevin Ku on Unsplash

Hello and welcome to this article on how to use Socket.io along-with NodeJS and ExpressJS for building a real-time Chat and Shared Workspace application.

Now I am well aware that there are various other articles, blogs and YouTube video explanations that will help you achieve the same result (after all, I too have read up and researched about all of this before making such a project! :) ).

However, I will try to bundle up all of that knowledge that I received after visiting 100+ websites and articles in this single article.

Prerequisites before you move on:

1. NodeJS installed on your system. (Click here for a tutorial).

2. Basic understanding of how NodeJS and ExpressJS already works. (If you don’t have it, you will still be able to follow along, but you might not be able to debug it if unknown errors suddenly pop out!).

3. A code editor to write our code in. I recommend VS Code, but feel free to choose any code editor you are comfortable with.

And that’s the end of the prerequisites!

NOW LET’S GET CODING…

First off create a folder and name it chat-app. Once that is done open your terminal and navigate to that folder. Now run “npm init” and complete the process. Once that is done, run the following commands :

1. npm install express

2. npm install socket.io

Then create a folder called public within which you will have your “index.html” and your client-side JavaScript named as “main.js” and inside the root directory (a.k.a chat-app) you will have your server-side JavaScript named “server.js”.

Once done, your folder structure should look something like this…

Aaron Lazarus Gomes | Folder structure

Now, let’s get into the front-end before we start writing our back-end code. In the “index.html” file let’s create a very basic (no styling) web-page which has an input field, submit button, messaging division (where all our messages will go) and finally a textarea which will act as our Shared Document between the users.

Below is how our HTML will look like…

Aaron Lazarus Gomes | Image of index.html

Let’s understand what is written, so right-off the bat we can see that everything is pretty basic, we have a Heading tag saying “This is a test” followed by an input tag with an “id”, a button, a dedicated space for all our messages and a textarea tag.

What seems different is the script tags, the second script tag is the one that refers to our client-side JavaScript file (quite obvious), but what is the meaning of the first script tag? Well, let’s keep this in mind as unchecked and move forward as the answer lies ahead 😉.

So this was pretty much it for the front-end of the application. Let’s move to getting the back-end up and running (for debugging purposes I recommend you use a package called “nodemon” so that you don’t have to keep restarting your server if any changes were made. To install it navigate to your root directory through the terminal, in this case the “chat-app” folder is the root directory and run the command “npm install nodemon”).

Now let’s setup our server using Express. Open your server.js file and type in the following.

const express = require("express")

const app = express();

const http = require("http").createServer(app);

const PORT = 3000 || process.env.PORT; http.listen(PORT, () => console.log("Running on port " + PORT);

This is the basic skeleton of setting up a server using express. But now we want to access our “index.html” file which is in the public folder. For that we use a function that express provides. Add the following line…

const express = require("express")

const app = express();

const http = require("http").createServer(app);

const PORT = 3000 || process.env.PORT; app.use(express.static("public")); http.listen(PORT, () => console.log("Running on port " + PORT);

Now in the terminal if we run the command “node server.js” or “nodemon server.js” (for those who installed nodemon) a message should be displayed in the console saying “Running on port 3000”. This is the same message that we wrote in the last line of the code. Our server is now up and running on our “http://localhost:3000”. To see it open up your browser and type in localhost:3000 and you should be able to see your index.html file. 😎

CRASH COURSE ON SOCKET.IO

The library Socket.io sort of functions like a key value pair. To send data you can use the following functions:

1. socket.send(value)

2. socket.emit(key, value)

3. socket.broadcast.emit(key, value)

4. io.emit(value)

And many more functions exists for various use cases. Now that we can emit, we also have to catch whatever we have emitted, right!

So, for that we have the socket.on(key, function(data) {} ); method.

Let’s look at an example…

//Emitting data

socket.emit("message", "Hi! This is a test");

socket.emit("message1", "Second message"); //Catching that data

socket.on("message", function(data) {

console.log(data);

});

In the above example, the output that will be printed on the screen is “Hi! This is a test”.

Remember I said that it sort of works like a key, value pair?

The key of the .emit() and the .on() method should be the same to catch the data that is being passed through the .emit() method.

For a detecting a connection to the socket we type in io.on(“connection”, function(socket) {}) and for detecting a disconnection we type in io.on(“disconnect”, function(socket) {}).

That’s all you need to know for now to move on with coding out the rest of the application! 😃

Let’s continue,

Go back to our server.js file and setup the socket connection. Add the following line…

const express = require("express")

const app = express();

const http = require("http").createServer(app);

const io = require("socket.io")(http);

const PORT = 3000 || process.env.PORT; app.use(express.static("public")); io.on("connection", function(socket) {

console.log("new user");

} http.listen(PORT, () => console.log("Running on port " + PORT);

In the above code we have now implemented socket connection for our server and if a user were to join our server, the statement “new user” would get printed.

However, if we open up our web browser and then view the console (not developer tools) we won’t be able to see that message. This is because we haven’t told our CLIENT side to connect to our server.

So now we jump into our main.js file and type in the following code…

const socket = io()

Now the question is, how are we gaining access to this “io()” function without importing it or requiring it?

Remember the first script tag that we included in our “index.html” file???

That is giving us the access to the “io()” function and that is why the two script tags are very very critical to include them and defer them in the index.html file.

Just by writing the above code we have now told our client to connect to our server… And now if we run our server and open our localhost:3000, we should be able to see the message “new user”.

Implementing the Chatting Functionality 😍 🌟

To implement the chat functionality now, we require to reference all of our elements in the DOM. So let’s do that in our “main.js”

Aaron Lazarus Gomes | main.js file

Now here’s where your knowledge of JavaScript comes into play. A couple of things need to be done, one -> we have to get the value from the input text field and onclicking of the button we have to emit it to all the users, two -> we have to get the value from the textarea while typing (“keyup” || “keydown”) and emit that to all the users.

We can do that by writing the following code…

Aaron Lazarus Gomes | main.js

Now on the button and the textarea we have added event listeners and then we are emitting that event to our server with (key, value) pair. So when we send it to our server, our server now has to send it to everyone connected to the socket, right? Therefore, we now go to our server.js file and catch the data and the broadcast it to everyone.

That can be done by writing the following code in the server.js file…

Aaron Lazarus Gomes | server.js

Once this is broadcasted from the server side, we have to now catch it again on the client. This is to make sure that all the users receive the same data that is being sent and thus enabling real-time communication a.k.a Chatting and Shared Document workspace.

Lines 12 and 17 are responsible for sending the data back to the clients that are connected to the socket. Each of them are sending the data back with a unique key and hence, we have to now catch them using that unique in the main.js file.

Let’s do the final implementation on our client side to finish off the project…

Aaron Lazarus Gomes | main.js

Here, from line 18 onwards, we see that we are catching the data coming in from the server and updating our DOM with those values.

Photo by Howie R on Unsplash

Hope you enjoyed reading through it and do let me know if you faced any difficulty! Thanks 🙌 😄