Note worthyπ
- This article assumes that you already have node.js installed on your computer. If you haven't, kindly do so here
Lets begin!
This write up hopes to walk you through the process of building a very simple 2 layer chat application.
Lets start by building the backend
- Create a folder and name it whatever you want, I'll be naming mine
SOCKET-APPLICATION-SERVER
. - Now you can use any IDE of your choice to open the folder. I prefer to use VScode.
- Open the terminal in this folder and initiate your node project with
npm init
. This command compiles all the main details of the your application such as name, version, description etc into apackage.json
file. - Now create your entry point file and give it a name of your choice. I'll name mine
app.js
. - Download the
socket.io
package by by runningnpm install socket.io
in the terminal. - set up your server in the the
app.js
file with the code below.
const httpServer = require('http').createServer((req, res) => {
res.setHeader('Access-Control-Allow-Origin', `${front end server link}`);
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
});
- Now require the
socket.io
package and create an object from it.
const io = require('socket.io')(httpServer, {
cors: {
origin: `${front end server link}`,
methods: ["GET", "POST"],
credentials: true
}
});
- Use the socket object created earlier (io) to initiate the connection.
io.on('connection', socket => {
});
- Now we are going receive the user's name entry from the frontend (this will make a lot more sense when we start building the frontend).
io.on('connection', socket => {
//new code added
socket.on('username', username => {
users[socket.id] = username
socket.broadcast.emit('user-in', username)
})
//new code added
});
- Since we now how the user's name after they connect, we can now worry about the user's (sender) message. We going to broadcast the user's (sender) message with to anyone one else online. We will do this by first receiving the message that tagged with
send-chat-message
then emit it with achat-message
tag. The tages help to distinguish between the messages coming in and those going out.
io.on('connection', socket => {
socket.on('username', username => {
users[socket.id] = username
socket.broadcast.emit('user-in', username)
})
//new code added
socket.on('send-chat-message', msg => {
socket.broadcast.emit('chat-message', {message: msg,
name: users[socket.id]})
})
//new code added
});
- We would like to notify the receiver once the sender disconnects or vice-versa.
const users = {}
io.on('connection', socket => {
socket.on('username', username => {
users[socket.id] = username
socket.broadcast.emit('user-in', username)
})
socket.on('send-chat-message', msg => {
socket.broadcast.emit('chat-message', {message: msg,
name: users[socket.id]})
})
//new code added
socket.on('disconnect', () => {
socket.broadcast.emit('user-disconnected', users[socket.id])
delete users[socket.id]
})
//new code added
});
- Finally set the port for the server and listen for requests
const PORT = process.env.PORT || 3000;
httpServer.listen(PORT, () => console.log(`Running server on π. \nListening on ${ PORT } π`));
- Start the server by running
node app.js
in the terminal. You can consider using nodemon which automatically refreshes your server anytime you make a change.
Lets start building the frontend
To aid with proper understanding the front end will run on a separate server.
- Create a folder and name it whatever you want, I'll be naming mine
SOCKET-APPLICATION-CLIENT
. - Open the folder in your IDE.
- Run
npm init
in the terminal for this folder - Download the
socket.io
package by by runningnpm install socket.io
in the terminal. - create a simple
index.html
file with the following body.
<body>
<div id="message-container">
</div>
<div id="send-container">
<input name="" placeholder="Type your message..." type="text" id="message-input">
<button id="end-button" type="submit">
<span id="submits">
<i class="fas fa-location-arrow"></i>
</span>
</button>
</div>
</body>
- Add the following script links inside your index.html
<head>
tag. Thesocket.io
instance will be created and sent from the backend. Thescript.js
file will use the instance to send and receive messages.
<script defer src="http://localhost:3000/socket.io/socket.io.js"></script>
<script defer src="./script.js"></script>
- Also download the
nodemon
package by by runningnpm install nodemon
in the terminal. This will restart your frontend server anytime you make a changes. - Now create your entry point file:
app.js
. - Set up your server in the the
app.js
by first runningnpm install express
. We'll need express to server static files like ourindex.html
page. - Now fill the
app.js
page with the code below.
var express = require('express'), app = express()
app.use('/', express.static('public'));
const PORT = process.env.PORT || 8000;
app.listen(PORT, () => console.log(`Running server on π. \nListening on ${ PORT } π`));
- Create the scripts.js file we linked to the
index.html
earlier. In the file, start by getting all the need DOM elements.
const mesaageForm = document.getElementById("submits")
const messageInput = document.getElementById('message-input')
const messageContainer = document.getElementById('message-container')
const userInfo = document.getElementById('user-info')
- Connect to the front end to backend socket
// connect to the server socket
const socket = io('http://localhost:3000', {
withCredentials: true
});
- Allow the socket to listen for messages. Only append the message to the receiver's view if it is not empty
//listen to the socket for content with the tag 'chat-message'
socket.on('chat-message', data => {
if (data.message != "") {
appendMessage(`${data.name}: ${data.message}`)
}
})
- Since we want to notify the receiver if sender disconnects or vice versa, we will use the socket to listen for disconnections.
//listen to the socket for user disconnection
socket.on('user-disconnected', name => {
appendMessage(`${name}: disconnected`)
})
- Now that our application is listening for all the necessary changes and messages, we can move on to obtaining the user's name
//ask the user for their name
const username = prompt('What is your name ?π')
socket.emit('username', username)
- Now we need to write functions that will append new messages to the screen for both the sender and receiver.
// send message to reciever
function appendMessage(message){
let man = messageContainer.scrollHeight + 500;
messageContainer.scroll = man
var wrapper= document.createElement('div');
wrapper.innerHTML = `
<div>
<p>${message}</p>
</div>
`
messageContainer.append(wrapper)
}
//show message on sender's screen
function appendMessageForMe(message){
messageContainer.scrollTop = messageContainer.scrollHeight;
var wrapper= document.createElement('div');
wrapper.innerHTML = `
<div>
<p>${message}</p>
</div>
`
messageContainer.append(wrapper)
}
- Finally we are going to use the event listener to activate the functions we just created whenever the user wants to send a message. To make things easier, we will activate the function when the user taps/clicks the send button, or presses the enter button after they have typed a message.
// if the user taps the send button or presses enter key, the message should be sent.
mesaageForm.addEventListener('click', e =>{
e.preventDefault()
const message = `${messageInput.value}`
if (message != "") {
// the emit method sends the message out with the tag: 'send-chat-message'
socket.emit('send-chat-message', message)
appendMessageForMe(message)
messageInput.value = ''
}
})
messageInput.addEventListener('keydown', e =>{
if (e.key === "Enter") {
e.preventDefault()
const message = `${messageInput.value}`
if (message != "") {
socket.emit('send-chat-message', message)
appendMessageForMe(message)
messageInput.value = ''
}
}
})
- Run
nodemon
in the terminal and go tohttp://localhost:8000/
- Don't forget to also run the backend server.
Conclusion
- we built a backend server that uses socket.io to recieve and reroute our messages to available users
- we also built a very simple π frontend to demonstrate the exchange of messages
- Don't forget to add your enhancements after you try this. I have an advanced version of this application on my repository. Check the backend out here here and the front end out here
Top comments (0)