Introduction
When you need bidirectional real-time communication, WebSockets are the answer. Unlike SSE (server-to-client only), WebSockets enable full-duplex communication for chat apps, games, collaborative tools, and live trading platforms.
Key Concepts
- Gateway: WebSocket endpoint handler (like a controller)
- @WebSocketGateway(): Decorator defining a WebSocket gateway
- @SubscribeMessage(): Handler for specific message types
- Socket.IO: Popular WebSocket library with fallbacks
Real World Context
Collaborative editing tools like Google Docs, multiplayer games, and live trading platforms all require bidirectional real-time communication. WebSockets maintain a persistent connection so both client and server can push data instantly without polling.
Deep Dive
Setup
bashnpm install @nestjs/websockets @nestjs/platform-socket.io socket.io
Basic Gateway
typescriptimport { WebSocketGateway, SubscribeMessage, MessageBody, WebSocketServer, OnGatewayConnection, OnGatewayDisconnect, } from '@nestjs/websockets'; import { Server, Socket } from 'socket.io'; @WebSocketGateway({ cors: { origin: '*' }, }) export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect { @WebSocketServer() server: Server; handleConnection(client: Socket) { console.log('Client connected:', client.id); } handleDisconnect(client: Socket) { console.log('Client disconnected:', client.id); } @SubscribeMessage('message') handleMessage(@MessageBody() data: { room: string; message: string }) { this.server.to(data.room).emit('message', data); return { event: 'message', data: 'Message sent' }; } @SubscribeMessage('join') handleJoinRoom(client: Socket, room: string) { client.join(room); return { event: 'joined', data: room }; } }
Broadcasting
typescript// To all clients this.server.emit('event', data); // To a room this.server.to('room-id').emit('event', data); // To a specific client this.server.to(client.id).emit('event', data); // To all except sender client.broadcast.emit('event', data);
Namespaces
typescript@WebSocketGateway({ namespace: '/admin' }) export class AdminGateway { // Only accessible at /admin namespace }
Guards and Pipes
typescript@WebSocketGateway() @UseGuards(WsAuthGuard) export class SecureGateway { @SubscribeMessage('secure-action') @UsePipes(ValidationPipe) handleSecure(@MessageBody() dto: SecureDto) { // Guarded and validated } }
Common Pitfalls
- CORS: Configure CORS for browser connections.
- Authentication: Implement WsAuthGuard for secure gateways.
- Memory leaks: Untracked connections can leak memory.
Best Practices
- Use rooms for group communication
- Implement heartbeat/ping for connection health
- Authenticate on connection
- Clean up resources on disconnect
Summary
WebSocketGateway handles bidirectional real-time communication. Use @SubscribeMessage() for handling events and server.emit() for broadcasting. Implement connection/disconnect handlers for cleanup and authentication.
Code Examples
typescript
@WebSocketGateway({ cors: { origin: '*' } })
export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect {
@WebSocketServer()
server: Server;
handleConnection(client: Socket) {
console.log('Client connected:', client.id);
}
@SubscribeMessage('message')
handleMessage(@MessageBody() data: { room: string; message: string }) {
this.server.to(data.room).emit('message', data);
}
}