WebSockets enable bidirectional, real-time communication between clients and servers.
Server Setup#
1import { WebSocketServer, WebSocket } from 'ws';
2
3const wss = new WebSocketServer({ port: 8080 });
4const clients = new Map<string, WebSocket>();
5
6wss.on('connection', (ws) => {
7 const clientId = crypto.randomUUID();
8 clients.set(clientId, ws);
9
10 ws.on('message', (data) => {
11 const message = JSON.parse(data.toString());
12 broadcast(message, clientId);
13 });
14
15 ws.on('close', () => clients.delete(clientId));
16});
17
18function broadcast(message: object, exclude?: string) {
19 clients.forEach((ws, id) => {
20 if (id !== exclude && ws.readyState === WebSocket.OPEN) {
21 ws.send(JSON.stringify(message));
22 }
23 });
24}Client with Reconnection#
1class WSClient {
2 private ws: WebSocket | null = null;
3 private attempts = 0;
4
5 connect(url: string) {
6 this.ws = new WebSocket(url);
7 this.ws.onopen = () => { this.attempts = 0; };
8 this.ws.onclose = () => this.reconnect(url);
9 }
10
11 private reconnect(url: string) {
12 const delay = Math.min(1000 * Math.pow(2, this.attempts++), 30000);
13 setTimeout(() => this.connect(url), delay);
14 }
15}Scaling with Redis#
1import Redis from 'ioredis';
2
3const pub = new Redis();
4const sub = new Redis();
5
6sub.subscribe('broadcasts');
7sub.on('message', (_, message) => {
8 wss.clients.forEach(client => client.send(message));
9});
10
11// Any server can broadcast
12pub.publish('broadcasts', JSON.stringify(message));Implement heartbeats, handle reconnection gracefully, and use Redis pub/sub for horizontal scaling.