Chat App using Socket.io
Tags: javascript, webdev, tutorial, chatapp
Published: 2021-06-22 09:38:07


 Have you ever wanted to create a real-time chat app or just curious about how the operation looks like under the hood?

![phone](https://media.giphy.com/media/l3vR2NcAVb9nhBoEE/giphy.gif)

Today we will be discussing how we can communicate with the client, browser, and server using NodeJS, ExpressJs, and Socket.io

First, let's define what a web socket is.
Web Socket is a computer communications protocol, providing full-duplex communication channels over a single TCP connection.
This communication is bi-directional and allows real-time data flow (transfer) because web sockets are always opened.

## Prerequisite
✔ NodeJS fundamentals
✔ JavaScript Fundamentals
✔ Fair knowledge of NPM

## Getting Started
### To-do
* Initiate our project
* Install Packages
* Set Up Express app and listen to the server
* Create a static middleware
* Use socket.io on the server-side (index.js) and in the front end (index.html)
* Querying Document Object Model (DOM)
* Broadcasting Messages

## Follow instructions to start the project
``` Initiate your project using npm init and pass the '-y' flag to default all questions. This creates your package.json file that tracks all the dependencies and list information about the project```
![carbon (2)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6e4lvxai1frx57oronpa.png)
 
``` Install dependencies: Express and Socket.io```
![carbon (4)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/idrs7i7z52yer3zuavlm.png)


```Install Nodemon to automatically restart the server, save it as a Dev dependency by using the --save-dev flag```
![carbon (5)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i6srstg7c3c68uqqi0lx.png)


Create an entry point, in this case, I will use index.js. Feel free to change your main entry file on the package.json
So let's set up our express application and create an instance of an express app

![carbon (1)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/de54nnaw51g08zy26dde.png)
 

Let's test ⛏ out the application by running Nodemon index on the terminal.
If you set up your app correctly, You will get the result below

```
[nodemon] starting `node index.js`
App is listening to server on port 3000
```

When you run localhost:3000 on your browser, the response is ```cannot GET /```. To be able to serve static files such as HTML, images, CSS to the browser, create a folder called "public", an index.html, and write the middleware in your index.js file.

```
// Static files middleware
app.use(express.static('public'));
```

✍ 
Note: Middleware is functions written between your request and response. Express automatically looks inside the public folder (static file) and serves the index.html.

For demonstration, let's flesh out a boilerplate inside the index.html file.

![carbon (6)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c8ehuyqdr2c9k50mp28d.png)
 So when you refresh the initial *localhost:3000* it will serve **Home Page** on the browser screen

Next up is to use socket.io in our index.js by first requiring the socket module
```const socket = require('socket.io');```

And then set up socket.io and link to the server the express app is listening to
```JavaScript
const io = socket(server);
```
At this point, the server is open and awaiting an event to be fired.

To make the WebSocket listen to an event when a particular client connects to the server, we write the function below.
```JavaScript
io.on('connection', (socket)=>{
console.log('Socket connected successfully')
);
```

Let load socket.io to our front-end to establish the communication between both ends.
[socket.io cdn](https://cdnjs.com/libraries/socket.io)

![socket i](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c7u0e3im32annvzpmv7s.JPG)

Copy the link above from the socket.io CDN and paste it inside the index.html file inside the public folder as a script file. (Highlighted in yellow).

![carbon (7)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xmbfv9t8o29d6rkfb9pl.png)
 
The next thing is to create a JavaScript file inside the public folder where we run the socket.io logic on the front-end. I will name it front_end_Chat.js and make reference to it inside the index.html. (highlighted in red)

![carbon (9)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7y9nkbhj8ripm45lqoaf.png).

### Explanation ✍
When we load the index.html served to us in the browser, the browser loads in the socket.io CDN (highlighted in yellow above) and then runs the front_end_Chat.js file.

Next is to establish the connection with the backend server inside the front_end_Chat.js file to create a web socket between both ends.
 
```JavaScript
// Make connection front-end setup
const socket = io.connect('http://localhost:3000');
```
 Here, when we load up the index.html file in the browser, we run the socket.io file, get to the front_end_Chat.js, make the connection on the just written function above, we listen to the **connection** on the backend inside the index.js file (see reference below) and log the message *' Socket connected successfully'* on our terminal when we refresh the page.

```JavaScript
// Backend connection
io.on('connection', (socket) => {
console.log('Socket connected successfully')
});
```

We can log different socket unique IDs to the console every time we refresh the server or a different computer connects to the same IP address. In this case http://localhost:3000
```JavaScript
// Backend connection
io.on('connection', (socket) => {
console.log('Socket connected successfully', socket.id)
});
```

At this point, we have set up socket.io both on the front end and the backend. Now let's look at how we can emit a message to different clients (browser) by transferring data between both ends through information we set on our front-end.

Here, we create inputs and a button in our index.html files to store and send user information and message.

```HTML
    <div id="tiny-chat">
        <div id="tiny-window">
            <div id="output"></div>
            <div id="feedback"></div>
        </div>
        <input id="handle" type="text" placeholder="Handle" />
        <input id="message" type="text" placeholder="Message" />
        <button id="send">Send</button>
    </div>
```

Thereafter, we flesh out the JavaScript on the front-end i.e front_end_Chat.js which interacts with the inputs and button above and emits a message through the JavaScript File from the client down to the server.

I used id to style the chatroom. Find the codebase on my GitHub.
[Github Link](https://github.com/drsimplegraffiti/tiny)

The next thing to do is to Query the DOM inside the front_end_Chat.js

```JavaScript
// Query DOM
const message = document.getElementById('message'),
    handle = document.getElementById('handle'),
    btn = document.getElementById('send'),
    output = document.getElementById('output');
```
The next thing is to emit a message when a user clicks on the send button using Vanilla JavaScript inside the same file.

```JavaScript
// Emit events
btn.addEventListener('click', function() {
    socket.emit('chat', {
        message: message.value,
        handle: handle.value
    });
    message.value = "";
});
```

##Explanation ✍
When we click the send button (btn), we listen for a click event, then fires a call back function, emit a message using the *socket.emit* function. The emit function takes two parameters (the name of the message which we call 'chat') and message (data sent to the server).

Next up, we need to handle the message sent from the front end on the server (index.js) by listening to the message.

```JavaScript
const io = socket(server);
io.on('connection', (socket) => {

    console.log('made socket connection', socket.id);

    // Handle chat event
    socket.on('chat', function(data) {
        console.log(data);
        io.sockets.emit('chat', data);
    });
```

On the front-end, We need a way to handle and output the *data* emitted on the socket.on function to the DOM. On the front_end_Chat.js we write the function below to listen for events.

```JavaScript
// Listen for events
socket.on('chat', function(data) {
    feedback.innerHTML = '';
    output.innerHTML += '<p><strong>' + data.handle + ': </strong>' + data.message + '</p>';
});
```

Lastly, we will need to broadcast the message emitted to the server to every web socket and client connected to it in real-time except the client sending the message.

To achieve this we need another input method to display the feedback sent from the server. Here, we use a div element on the index.html and make a reference to it in the front_end_Chat.js
![carbon (10)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ilq1o0k1c154y1koow4d.png)
 
![carbon (11)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c3t32qbfordklezwdjzy.png)
 
Then we attach an event listener to the message input using the keypress event and emit a message to the server

![carbon (12)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i71jt6gwsingj0jtn2l5.png)
 
Next, we navigate into the server-side (index.js) and use the *broadcast.emit* method

![carbon (13)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ksj5bcbdkisotk36koaf.png)

And then we handle the on the front_end_Chat.js
![carbon (15)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bnam6zx63sfwyrgjlu84.png)
 
Final test should look like the video in the link below. 

[Tiny Video](https://github.com/drsimplegraffiti/tiny/blob/main/README.md)

I hope this guide is helpful😁.Thanks
![over](https://media.giphy.com/media/iYn4qXCb15EKD0i23e/giphy.gif)

## Resources
[Web Socket Definition](https://en.wikipedia.org/wiki/WebSocket)
[Video Reference](https://www.youtube.com/watch?v=vQjiN8Qgs3c&t=209s)