NestJS et WebSockets en 2026 : Temps Réel, Gateway et Questions d'Entretien
Maîtrisez les WebSockets NestJS avec les patterns Gateway, l'intégration Socket.IO, l'authentification, la gestion des erreurs et les questions d'entretien courantes pour 2026.

Les WebSockets NestJS offrent une approche structurée de la communication temps réel grâce au pattern Gateway. Contrairement aux implémentations WebSocket brutes, NestJS abstrait la complexité via des décorateurs et s'intègre parfaitement au système d'injection de dépendances.
Un WebSocket Gateway dans NestJS est une classe décorée avec @WebSocketGateway() qui gère la communication bidirectionnelle entre client et serveur. Il supporte plusieurs adaptateurs (Socket.IO, ws) et s'intègre aux Guards, Pipes et Interceptors de NestJS.
Configuration d'un WebSocket Gateway avec Socket.IO
L'adaptateur par défaut dans NestJS utilise Socket.IO, qui fournit la reconnexion automatique, le support des rooms et le fallback vers le long-polling HTTP. L'installation nécessite le package spécifique à la plateforme en plus du module WebSockets principal.
# terminal
npm install @nestjs/websockets @nestjs/platform-socket.io socket.ioUn gateway basique écoute les messages entrants et peut diffuser des réponses aux clients connectés.
import {
WebSocketGateway,
WebSocketServer,
SubscribeMessage,
MessageBody,
ConnectedSocket,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
@WebSocketGateway({
cors: { origin: '*' }, // Configure CORS pour les clients navigateur
})
export class ChatGateway {
@WebSocketServer()
server: Server; // Accès au serveur Socket.IO sous-jacent
@SubscribeMessage('message') // Écoute les événements 'message'
handleMessage(
@MessageBody() data: { text: string; room: string },
@ConnectedSocket() client: Socket,
): void {
// Diffuse à tous les clients dans la room sauf l'expéditeur
client.to(data.room).emit('message', {
text: data.text,
senderId: client.id,
timestamp: Date.now(),
});
}
}Le décorateur @SubscribeMessage lie une méthode à un nom d'événement spécifique. @MessageBody() extrait le payload, tandis que @ConnectedSocket() fournit l'accès au socket client pour des réponses ciblées.
Hooks de Cycle de Vie pour la Gestion des Connexions
Les gateways NestJS implémentent des interfaces de cycle de vie pour gérer les connexions et déconnexions des clients. Ces hooks permettent le nettoyage des ressources, le suivi de présence et la validation des connexions.
import {
WebSocketGateway,
OnGatewayConnection,
OnGatewayDisconnect,
OnGatewayInit,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
import { Logger } from '@nestjs/common';
@WebSocketGateway()
export class PresenceGateway
implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect
{
private readonly logger = new Logger(PresenceGateway.name);
private connectedUsers = new Map<string, { joinedAt: Date }>();
afterInit(server: Server): void {
// Appelé une fois lors de l'initialisation du gateway
this.logger.log('WebSocket Gateway initialisé');
}
handleConnection(client: Socket): void {
// Suivre les nouvelles connexions
this.connectedUsers.set(client.id, { joinedAt: new Date() });
this.logger.log(`Client connecté: ${client.id}`);
}
handleDisconnect(client: Socket): void {
// Nettoyage lors de la déconnexion
this.connectedUsers.delete(client.id);
this.logger.log(`Client déconnecté: ${client.id}`);
}
}Les trois interfaces de cycle de vie servent des objectifs distincts : OnGatewayInit s'exécute une fois au démarrage, OnGatewayConnection se déclenche à chaque connexion client, et OnGatewayDisconnect gère le nettoyage quand les clients partent.
Authentification avec les Guards WebSocket
Les connexions WebSocket nécessitent une validation d'authentification avant d'autoriser l'accès aux événements protégés. Les Guards NestJS fonctionnent avec les gateways, bien que le contexte d'exécution diffère des requêtes HTTP. La documentation officielle NestJS WebSockets couvre l'intégration des guards en détail.
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { WsException } from '@nestjs/websockets';
import { JwtService } from '@nestjs/jwt';
import { Socket } from 'socket.io';
@Injectable()
export class WsAuthGuard implements CanActivate {
constructor(private jwtService: JwtService) {}
canActivate(context: ExecutionContext): boolean {
const client: Socket = context.switchToWs().getClient();
// Extraire le token depuis handshake auth ou query params
const token =
client.handshake.auth?.token ||
client.handshake.query?.token;
if (!token) {
throw new WsException('Token d\'authentification manquant');
}
try {
const payload = this.jwtService.verify(token as string);
// Attacher les données utilisateur au socket pour utilisation ultérieure
client.data.user = payload;
return true;
} catch {
throw new WsException('Token invalide');
}
}
}Le guard s'applique à la classe gateway ou aux gestionnaires de messages individuels via le décorateur @UseGuards(). La classe WsException lance des erreurs que le client reçoit via l'événement error de Socket.IO.
import { UseGuards } from '@nestjs/common';
import { WebSocketGateway, SubscribeMessage } from '@nestjs/websockets';
import { WsAuthGuard } from './ws-auth.guard';
@WebSocketGateway()
@UseGuards(WsAuthGuard) // Protège tous les handlers dans ce gateway
export class SecureChatGateway {
@SubscribeMessage('privateMessage')
handlePrivateMessage(): void {
// Seuls les clients authentifiés atteignent ce handler
}
}Pour les questions d'authentification au niveau module, consultez le module d'entretien NestJS sur l'authentification et JWT couvrant les stratégies JWT et la gestion des sessions.
Prêt à réussir tes entretiens Node.js / NestJS ?
Entraîne-toi avec nos simulateurs interactifs, fiches express et tests techniques.
Patterns de Diffusion Basés sur les Rooms
Les rooms Socket.IO permettent la livraison ciblée de messages vers des sous-ensembles de clients connectés. Les cas d'usage courants incluent les salons de chat, les lobbies de jeux et les fonctionnalités de collaboration en direct.
import {
WebSocketGateway,
SubscribeMessage,
ConnectedSocket,
MessageBody,
WebSocketServer,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
@WebSocketGateway()
export class RoomGateway {
@WebSocketServer()
server: Server;
@SubscribeMessage('joinRoom')
handleJoinRoom(
@MessageBody() roomId: string,
@ConnectedSocket() client: Socket,
): { event: string; data: string } {
// Ajouter le client à la room spécifiée
client.join(roomId);
// Notifier les autres dans la room
client.to(roomId).emit('userJoined', { userId: client.id });
return { event: 'joinedRoom', data: roomId };
}
@SubscribeMessage('leaveRoom')
handleLeaveRoom(
@MessageBody() roomId: string,
@ConnectedSocket() client: Socket,
): void {
client.leave(roomId);
client.to(roomId).emit('userLeft', { userId: client.id });
}
@SubscribeMessage('roomBroadcast')
handleRoomBroadcast(
@MessageBody() payload: { roomId: string; message: string },
): void {
// Envoyer à tous les clients dans la room, y compris l'expéditeur
this.server.to(payload.roomId).emit('roomMessage', payload.message);
}
}La distinction entre client.to(room).emit() et server.to(room).emit() est importante : le premier exclut l'expéditeur, tandis que le second inclut tous les membres de la room.
Gestion des Erreurs avec les Filtres d'Exception
Les exceptions WebSocket nécessitent des filtres dédiés car les filtres d'exception HTTP ne s'appliquent pas aux contextes gateway. Les filtres personnalisés capturent WsException et formatent les réponses d'erreur pour les clients.
import { Catch, ArgumentsHost, ExceptionFilter } from '@nestjs/common';
import { WsException } from '@nestjs/websockets';
import { Socket } from 'socket.io';
@Catch(WsException)
export class WsExceptionFilter implements ExceptionFilter {
catch(exception: WsException, host: ArgumentsHost): void {
const client: Socket = host.switchToWs().getClient();
const error = exception.getError();
// Envoyer une erreur structurée au client
client.emit('error', {
type: 'WsException',
message: typeof error === 'string' ? error : error,
timestamp: new Date().toISOString(),
});
}
}Les filtres s'appliquent au niveau du gateway pour une gestion cohérente des erreurs sur tous les gestionnaires de messages.
import { UseFilters } from '@nestjs/common';
import { WebSocketGateway } from '@nestjs/websockets';
import { WsExceptionFilter } from './ws-exception.filter';
@WebSocketGateway()
@UseFilters(WsExceptionFilter)
export class FilteredGateway {
// Tous les handlers bénéficient d'une gestion centralisée des erreurs
}Ce pattern reflète la philosophie NestJS des décorateurs et filtres décrite dans le module middleware et intercepteurs.
Mise à l'Échelle des WebSockets avec l'Adaptateur Redis
Les déploiements WebSocket mono-serveur échouent lorsque le load balancing distribue les clients sur plusieurs instances. L'adaptateur Redis Socket.IO synchronise les événements entre les instances via un mécanisme pub/sub.
import { Module } from '@nestjs/common';
import { createAdapter } from '@socket.io/redis-adapter';
import { createClient } from 'redis';
import { ChatGateway } from './chat.gateway';
@Module({
providers: [
ChatGateway,
{
provide: 'REDIS_ADAPTER',
useFactory: async () => {
const pubClient = createClient({ url: process.env.REDIS_URL });
const subClient = pubClient.duplicate();
await Promise.all([pubClient.connect(), subClient.connect()]);
return createAdapter(pubClient, subClient);
},
},
],
})
export class AppModule {}Le gateway utilise ensuite l'adaptateur pour la communication inter-instances.
import {
WebSocketGateway,
WebSocketServer,
OnGatewayInit,
} from '@nestjs/websockets';
import { Inject } from '@nestjs/common';
import { Server } from 'socket.io';
import { Adapter } from 'socket.io-adapter';
@WebSocketGateway()
export class ScalableGateway implements OnGatewayInit {
@WebSocketServer()
server: Server;
constructor(@Inject('REDIS_ADAPTER') private redisAdapter: Adapter) {}
afterInit(): void {
// Attacher l'adaptateur Redis pour le support multi-instances
this.server.adapter(this.redisAdapter as any);
}
}Avec l'adaptateur Redis, un message émis sur une instance serveur atteint les clients connectés à n'importe quelle instance du cluster.
Questions d'Entretien Courantes sur les WebSockets NestJS
Les entretiens techniques sondent souvent la compréhension des décisions d'architecture temps réel et des détails d'implémentation spécifiques à NestJS.
Comment NestJS gère-t-il l'authentification WebSocket différemment de HTTP ?
Les middlewares HTTP ne s'exécutent pas pour les connexions WebSocket. L'authentification se produit pendant la phase de handshake ou via des Guards appliqués au gateway. La validation du token se fait généralement dans handleConnection() ou un Guard personnalisé qui lit depuis socket.handshake.auth.
Quelle est la différence entre la configuration du port @WebSocketGateway() et le port principal de l'application ?
Par défaut, les gateways WebSocket partagent le port du serveur HTTP. Spécifier un port dans @WebSocketGateway(3001) crée un serveur WebSocket séparé sur ce port. Les ports partagés simplifient le déploiement mais nécessitent un routage basé sur le chemin (/socket.io) lors de l'utilisation de reverse proxies.
Comment tester les gateways WebSocket dans NestJS ?
Les utilitaires de test NestJS supportent le test des gateways via Test.createTestingModule(). La bibliothèque socket.io-client se connecte au serveur de test. Les hooks de cycle de vie et les gestionnaires de messages sont testés en émettant des événements et en vérifiant les réponses ou les effets de bord.
import { Test } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { io, Socket } from 'socket.io-client';
import { ChatGateway } from './chat.gateway';
describe('ChatGateway', () => {
let app: INestApplication;
let client: Socket;
beforeAll(async () => {
const module = await Test.createTestingModule({
providers: [ChatGateway],
}).compile();
app = module.createNestApplication();
await app.listen(3000);
client = io('http://localhost:3000');
});
afterAll(async () => {
client.disconnect();
await app.close();
});
it('reçoit un accusé de réception de message', (done) => {
client.emit('message', { text: 'test', room: 'lobby' });
client.on('message', (data) => {
expect(data.text).toBe('test');
done();
});
});
});Quand utiliser l'adaptateur ws au lieu de Socket.IO ?
L'adaptateur bibliothèque ws (@nestjs/platform-ws) offre une surcharge moindre pour les applications qui n'ont pas besoin des fonctionnalités Socket.IO comme la reconnexion automatique, les rooms ou les transports de fallback. Les systèmes de trading haute fréquence et les serveurs de jeux préfèrent souvent ws pour une latence réduite.
Pour les concepts d'architecture NestJS plus larges, l'article connexe sur Guards, Intercepteurs et Architecture Modulaire couvre comment ces patterns s'intègrent à travers les contextes HTTP et WebSocket.
Conclusion
- Les WebSocket Gateways s'intègrent à l'injection de dépendances, aux Guards et aux Filters de NestJS pour des patterns cohérents entre HTTP et endpoints temps réel
- Les hooks de cycle de vie (
OnGatewayConnection,OnGatewayDisconnect) gèrent le suivi de présence et le nettoyage des ressources - Les flux d'authentification diffèrent de HTTP ; la validation du token se produit pendant le handshake ou via des Guards WebSocket dédiés
- La diffusion basée sur les rooms avec Socket.IO permet un messaging ciblé sans gérer manuellement les listes de sockets
- L'adaptateur Redis résout la mise à l'échelle horizontale en synchronisant les événements entre plusieurs instances serveur
- Les filtres d'exception nécessitent des implémentations spécifiques aux WebSocket utilisant
WsExceptionet des filtres personnalisés
Passe à la pratique !
Teste tes connaissances avec nos simulateurs d'entretien et tests techniques.
Partager
Articles similaires

NestJS et GraphQL en 2026 : Schémas, Resolvers et Questions d'Entretien
Guide complet sur l'intégration de NestJS avec GraphQL : approches code-first et schema-first, création de resolvers, et préparation aux entretiens techniques en 2026.

NestJS et TypeORM en 2026 : migrations, relations et questions d'entretien
Maîtriser l'intégration NestJS TypeORM avec les migrations de TypeORM 1.0, les relations entre entités, le pattern repository et les questions d'entretien courantes pour les développeurs backend.

Node.js 24 en 2026 : URLPattern, Permission Model et questions d'entretien
Node.js 24 LTS apporte un Permission Model stable, URLPattern global, la gestion explicite des ressources avec using/await using et V8 13.6. Plongée dans les fonctionnalités qui comptent en production et en entretien.