A deep dive into creating a real-time chat application using WebSockets in Node.js.
2024-12-14
Real-time applications like chat systems, collaborative tools, or live notifications require a different approach compared to traditional request-response web applications. In this article, we’ll explore how to build a real-time chat app using WebSockets and Node.js, step by step.
What Are WebSockets?
WebSockets provide a full-duplex communication channel over a single TCP connection. Unlike HTTP, where the client initiates a request and waits for a response, WebSockets enable a persistent connection that allows the server to send data to the client without being polled.
This makes WebSockets perfect for real-time applications where low latency is critical.
Setting Up the Project
Having Node.js installed let’s start by creating a new Node.js project.
1. Initialize the Project
Run the following commands to initialize a new Node.js project:
mkdir realtime-chat
cd realtime-chat
npm init -y
2. Install Dependencies
We’ll use the ws
library, a lightweight WebSocket implementation for Node.js:
npm install ws express
ws
: Provides WebSocket support.express
: Serves the frontend for our chat app.
3. Directory Structure
Create the following directory structure:
realtime-chat/
├── public/
│ ├── index.html
│ └── script.js
├── server.js
└── package.json
Building the Backend
In the server.js
file, we’ll set up an Express server to serve our frontend and a WebSocket server for real-time communication.
const express = require("express");
const http = require("http");
const WebSocket = require("ws");
const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
// Serve static files from the public directory
app.use(express.static("public"));
// Handle WebSocket connections
wss.on("connection", (ws) => {
console.log("A new client connected!");
ws.on("message", (message) => {
console.log(`Received: ${message}`);
// Broadcast the message to all connected clients
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
});
ws.on("close", () => {
console.log("A client disconnected.");
});
});
// Start the server
const PORT = 3000;
server.listen(PORT, () => {
console.log(`Server is running on <http://localhost:${PORT}`);
});
Creating the Frontend
The frontend will be a simple HTML page with a basic chat interface.
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Real-Time Chat</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
.chat {
max-width: 600px;
margin: 50px auto;
border: 1px solid #ccc;
padding: 20px;
border-radius: 5px;
}
.messages {
height: 300px;
overflow-y: scroll;
border: 1px solid #ccc;
padding: 10px;
margin-bottom: 20px;
}
.messages div {
margin-bottom: 10px;
}
.input {
display: flex;
}
.input input {
flex: 1;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}
.input button {
padding: 10px;
border: none;
background-color: #007bff;
color: white;
border-radius: 5px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="chat">
<div class="messages" id="messages"></div>
<div class="input">
<input type="text" id="messageInput" placeholder="Type a message..." />
<button id="sendButton">Send</button>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
public/script.js
The frontend JavaScript will handle sending and receiving messages via the WebSocket connection.
const ws = new WebSocket("ws://localhost:3000");
const messagesDiv = document.getElementById("messages");
const messageInput = document.getElementById("messageInput");
const sendButton = document.getElementById("sendButton");
// Display incoming messages
ws.onmessage = (event) => {
event.data.text().then((text) => {
const message = document.createElement("div");
message.textContent = text;
messagesDiv.appendChild(message);
messagesDiv.scrollTop = messagesDiv.scrollHeight;
});
};
// Send a message when the button is clicked
sendButton.addEventListener("click", () => {
const message = messageInput.value;
ws.send(message);
messageInput.value = "";
});
// Handle the Enter key
messageInput.addEventListener("keypress", (event) => {
if (event.key === "Enter") {
sendButton.click();
}
});
Running the Application
-
Start the server:
node server.js
-
Open
http://localhost:3000
in your browser. -
Open multiple browser tabs and start chatting! Messages will appear in real time across all connected clients.
Next Steps
This is a basic real-time chat app to get you started with WebSockets. You can extend it further:
- Add user authentication.
- Store messages in a database.
- Deploy the application to a cloud platform like Vercel or AWS.
WebSockets are a powerful tool for building real-time applications. With this foundational example, you’re ready to explore more complex use cases!