WebSocket is a communication protocol that enables real-time, two-way interaction between a client and a server over a single, long-lived connection. Unlike traditional HTTP, which follows a request-response model, WebSocket allows for full-duplex communication, meaning both the client and the server can send and receive messages at any time. Integrating WebSockets with Express.js can be powerful for applications that require live updates, such as chat apps, collaborative tools, and live notifications.
WebSocket is a protocol designed for real-time applications. It allows a persistent connection between the client and server, enabling low-latency communication. This is different from HTTP, where each request opens a new connection. WebSocket operates over the same port as HTTP/HTTPS (80/443) but establishes a different kind of connection.
WebSockets are ideal for applications that need:
Express.js doesn’t natively support WebSocket, but it can be easily integrated with WebSocket libraries, such as ws
, which provides a lightweight and efficient WebSocket implementation. You can also use socket.io
, which builds on WebSocket but includes additional features.
First, let’s set up the ws
library.
npm install express ws
To create a WebSocket server with Express.js, you need to initialize both Express and the WebSocket server, then configure them to work together.
ws
library.
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 });
// Basic route
app.get('/', (req, res) => {
res.send('Welcome to WebSocket Integration with Express.js!');
});
// WebSocket connection event
wss.on('connection', (ws) => {
console.log('New client connected');
// Send a welcome message to the client
ws.send('Welcome to the WebSocket server!');
// Listen for messages from the client
ws.on('message', (message) => {
console.log(`Received message: ${message}`);
});
// Handle client disconnection
ws.on('close', () => {
console.log('Client disconnected');
});
});
// Start the server
server.listen(3000, () => {
console.log('Server is running on port 3000');
});
wss
) is created using the same server as Express (http.createServer(app)
).wss.on('connection')
: Event fired when a new client connects.ws.send()
: Sends a message to the client.ws.on('message')
: Listens for messages from the client.ws.on('close')
: Handles client disconnection.Let’s create a simple real-time chat application where clients can send and receive messages in real time.
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 the chat page
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
// Broadcast messages to all connected clients
function broadcast(data) {
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
}
// Handle new WebSocket connections
wss.on('connection', (ws) => {
ws.on('message', (message) => {
console.log(`Received: ${message}`);
broadcast(message); // Broadcast the received message
});
});
server.listen(3000, () => {
console.log('Chat server is running on port 3000');
});
broadcast
function sends the received message to all connected clients.
Chat App
Chat Room
sendMessage()
function sends the user’s message to the server.ws.onmessage
: Receives broadcast messages and displays them.Broadcasting messages is essential in multi-client applications. The wss.clients
property contains all connected clients, and we can iterate over them to send messages.
function broadcast(data) {
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
}
This method is effective for simple applications where all clients need to receive the same message.
WebSocket connections don’t support headers, so traditional token-based authentication must be handled manually. You can use query strings or send tokens as the first message.
wss.on('connection', (ws, req) => {
const params = new URLSearchParams(req.url.split('?')[1]);
const token = params.get('token');
if (validateToken(token)) {
console.log('Client authenticated');
} else {
ws.close(1008, 'Unauthorized'); // Close connection if unauthorized
}
});
Error handling is essential for a stable WebSocket server. Common error handling includes checking if a client is closed or handling connection failures.
ws.on('error', (err) => {
console.error('WebSocket error:', err);
});
When scaling WebSocket connections across multiple servers, use a shared storage like Redis to manage messages between servers.
Using ws
with Redis:
redis
and redis-adapter
.
const redis = require('redis');
const redisClient = redis.createClient();
Integrating WebSocket with Express.js provides a way to create dynamic, real-time applications efficiently. Using libraries like ws, you can establish persistent, two-way communication channels that enable data to flow seamlessly between clients and servers. From basic configurations to complex broadcast and authentication setups, WebSocket integration with Express can power a wide range of applications, from simple chats to large-scale real-time systems. Happy Coding!❤️