NestJS i WebSockets w 2026: Komunikacja w Czasie Rzeczywistym, Gateway i Pytania Rekrutacyjne
Kompleksowy przewodnik po WebSockets w NestJS z wzorcem Gateway, integracją Socket.IO, uwierzytelnianiem, obsługą błędów i pytaniami rekrutacyjnymi na 2026 rok.

NestJS WebSockets oferują strukturalne podejście do komunikacji w czasie rzeczywistym przy użyciu wzorca Gateway. W przeciwieństwie do surowych implementacji WebSocket, NestJS abstrahuje złożoność poprzez dekoratory i bezproblemowo integruje się z systemem wstrzykiwania zależności.
WebSocket Gateway w NestJS to klasa ozdobiona dekoratorem @WebSocketGateway(), która obsługuje dwukierunkową komunikację między klientem a serwerem. Obsługuje wiele adapterów (Socket.IO, ws) i integruje się z Guards, Pipes oraz Interceptors w NestJS.
Konfiguracja WebSocket Gateway z Socket.IO
Domyślny adapter w NestJS wykorzystuje Socket.IO, który zapewnia automatyczne ponowne łączenie, obsługę pokoi i fallback do HTTP long-polling. Instalacja wymaga pakietu specyficznego dla platformy wraz z głównym modułem WebSockets.
# terminal
npm install @nestjs/websockets @nestjs/platform-socket.io socket.ioPodstawowy gateway nasłuchuje przychodzących wiadomości i może rozsyłać odpowiedzi do połączonych klientów.
import {
WebSocketGateway,
WebSocketServer,
SubscribeMessage,
MessageBody,
ConnectedSocket,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
@WebSocketGateway({
cors: { origin: '*' }, // Configure CORS for browser clients
})
export class ChatGateway {
@WebSocketServer()
server: Server; // Access to the underlying Socket.IO server
@SubscribeMessage('message') // Listen for 'message' events
handleMessage(
@MessageBody() data: { text: string; room: string },
@ConnectedSocket() client: Socket,
): void {
// Broadcast to all clients in the room except sender
client.to(data.room).emit('message', {
text: data.text,
senderId: client.id,
timestamp: Date.now(),
});
}
}Dekorator @SubscribeMessage wiąże metodę z konkretną nazwą zdarzenia. @MessageBody() wyodrębnia payload, podczas gdy @ConnectedSocket() zapewnia dostęp do gniazda klienta dla ukierunkowanych odpowiedzi.
Hooki Cyklu Życia do Zarządzania Połączeniami
Gatewaye NestJS implementują interfejsy cyklu życia do obsługi połączeń i rozłączeń klientów. Te hooki umożliwiają czyszczenie zasobów, śledzenie obecności i walidację połączeń.
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 {
// Called once when the gateway initializes
this.logger.log('WebSocket Gateway initialized');
}
handleConnection(client: Socket): void {
// Track new connections
this.connectedUsers.set(client.id, { joinedAt: new Date() });
this.logger.log(`Client connected: ${client.id}`);
}
handleDisconnect(client: Socket): void {
// Cleanup on disconnect
this.connectedUsers.delete(client.id);
this.logger.log(`Client disconnected: ${client.id}`);
}
}Trzy interfejsy cyklu życia służą różnym celom: OnGatewayInit uruchamia się raz przy starcie, OnGatewayConnection wyzwala się przy każdym połączeniu klienta, a OnGatewayDisconnect obsługuje czyszczenie gdy klienci opuszczają połączenie.
Uwierzytelnianie z WebSocket Guards
Połączenia WebSocket wymagają walidacji uwierzytelniania przed zezwoleniem na dostęp do chronionych zdarzeń. NestJS Guards współpracują z gatewayami, chociaż kontekst wykonania różni się od żądań HTTP. Oficjalna dokumentacja NestJS WebSockets szczegółowo opisuje integrację guards.
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();
// Extract token from handshake auth or query params
const token =
client.handshake.auth?.token ||
client.handshake.query?.token;
if (!token) {
throw new WsException('Missing authentication token');
}
try {
const payload = this.jwtService.verify(token as string);
// Attach user data to socket for later use
client.data.user = payload;
return true;
} catch {
throw new WsException('Invalid token');
}
}
}Guard stosuje się do klasy gateway lub poszczególnych handlerów wiadomości za pomocą dekoratora @UseGuards(). Klasa WsException rzuca błędy, które klient otrzymuje poprzez zdarzenie error Socket.IO.
import { UseGuards } from '@nestjs/common';
import { WebSocketGateway, SubscribeMessage } from '@nestjs/websockets';
import { WsAuthGuard } from './ws-auth.guard';
@WebSocketGateway()
@UseGuards(WsAuthGuard) // Protect all handlers in this gateway
export class SecureChatGateway {
@SubscribeMessage('privateMessage')
handlePrivateMessage(): void {
// Only authenticated clients reach this handler
}
}Dla pytań dotyczących uwierzytelniania na poziomie modułu warto zapoznać się z modułem pytań rekrutacyjnych NestJS o uwierzytelnianiu obejmującym strategie JWT i zarządzanie sesjami.
Gotowy na rozmowy o Node.js / NestJS?
Ćwicz z naszymi interaktywnymi symulatorami, flashcards i testami technicznymi.
Wzorce Rozgłaszania Oparte na Pokojach
Pokoje Socket.IO umożliwiają ukierunkowane dostarczanie wiadomości do podzbiorów połączonych klientów. Typowe przypadki użycia obejmują pokoje czatu, lobby gier i funkcje współpracy na żywo.
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 } {
// Add client to the specified room
client.join(roomId);
// Notify others in the 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 {
// Send to all clients in room, including sender
this.server.to(payload.roomId).emit('roomMessage', payload.message);
}
}Różnica między client.to(room).emit() a server.to(room).emit() ma znaczenie: pierwsza wyklucza nadawcę, podczas gdy druga obejmuje wszystkich członków pokoju.
Obsługa Błędów z Filtrami Wyjątków
Wyjątki WebSocket wymagają dedykowanych filtrów, ponieważ filtry wyjątków HTTP nie mają zastosowania w kontekstach gateway. Niestandardowe filtry przechwytują WsException i formatują odpowiedzi błędów dla klientów.
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();
// Send structured error to client
client.emit('error', {
type: 'WsException',
message: typeof error === 'string' ? error : error,
timestamp: new Date().toISOString(),
});
}
}Filtry stosuje się na poziomie gateway dla spójnej obsługi błędów we wszystkich handlerach wiadomości.
import { UseFilters } from '@nestjs/common';
import { WebSocketGateway } from '@nestjs/websockets';
import { WsExceptionFilter } from './ws-exception.filter';
@WebSocketGateway()
@UseFilters(WsExceptionFilter)
export class FilteredGateway {
// All handlers benefit from centralized error handling
}Ten wzorzec odzwierciedla filozofię NestJS dotyczącą dekoratorów i filtrów opisaną w module middleware i interceptors.
Skalowanie WebSockets z Adapterem Redis
Wdrożenia WebSocket na pojedynczym serwerze zawodzą, gdy load balancing rozprowadza klientów na wiele instancji. Adapter Redis Socket.IO synchronizuje zdarzenia między instancjami poprzez mechanizm 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 {}Następnie gateway używa adaptera do komunikacji między instancjami.
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 {
// Attach Redis adapter for multi-instance support
this.server.adapter(this.redisAdapter as any);
}
}Z adapterem Redis wiadomość wyemitowana na jednej instancji serwera dociera do klientów połączonych z dowolną instancją w klastrze.
Popularne Pytania Rekrutacyjne dotyczące NestJS WebSockets
Rozmowy techniczne często badają zrozumienie decyzji architektonicznych dotyczących czasu rzeczywistego i szczegółów implementacyjnych specyficznych dla NestJS.
Jak NestJS obsługuje uwierzytelnianie WebSocket inaczej niż HTTP?
Middleware HTTP nie wykonuje się dla połączeń WebSocket. Uwierzytelnianie odbywa się podczas fazy handshake lub poprzez Guards zastosowane do gateway. Walidacja tokenów zazwyczaj odbywa się w handleConnection() lub w niestandardowym Guard, który odczytuje z socket.handshake.auth.
Jaka jest różnica między konfiguracją portu @WebSocketGateway() a głównym portem aplikacji?
Domyślnie gatewaye WebSocket współdzielą port serwera HTTP. Określenie portu w @WebSocketGateway(3001) tworzy oddzielny serwer WebSocket na tym porcie. Współdzielone porty upraszczają wdrożenie, ale wymagają routingu opartego na ścieżkach (/socket.io) przy użyciu reverse proxy.
Jak testować gatewaye WebSocket w NestJS?
Narzędzia testowe NestJS wspierają testowanie gateway poprzez Test.createTestingModule(). Biblioteka socket.io-client łączy się z serwerem testowym. Hooki cyklu życia i handlery wiadomości testuje się emitując zdarzenia i sprawdzając odpowiedzi lub efekty uboczne.
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('receives message acknowledgment', (done) => {
client.emit('message', { text: 'test', room: 'lobby' });
client.on('message', (data) => {
expect(data.text).toBe('test');
done();
});
});
});Kiedy należy używać adaptera ws zamiast Socket.IO?
Adapter biblioteki ws (@nestjs/platform-ws) oferuje mniejszy narzut dla aplikacji, które nie potrzebują funkcji Socket.IO takich jak automatyczne ponowne łączenie, pokoje czy transporty fallback. Systemy handlu wysokiej częstotliwości i serwery gier często preferują ws ze względu na zmniejszone opóźnienia.
Dla szerszych koncepcji architektury NestJS, powiązany artykuł o Guards, Interceptors i Architekturze Modularnej opisuje jak te wzorce integrują się w kontekstach HTTP i WebSocket.
Podsumowanie
- WebSocket Gateways integrują się z dependency injection NestJS, Guards i Filters dla spójnych wzorców w endpointach HTTP i czasu rzeczywistego
- Hooki cyklu życia (
OnGatewayConnection,OnGatewayDisconnect) zarządzają śledzeniem obecności i czyszczeniem zasobów - Przepływy uwierzytelniania różnią się od HTTP; walidacja tokenów odbywa się podczas handshake lub poprzez dedykowane WebSocket Guards
- Rozgłaszanie oparte na pokojach z Socket.IO umożliwia ukierunkowane wiadomości bez ręcznego zarządzania listami socketów
- Adapter Redis rozwiązuje skalowanie horyzontalne przez synchronizację zdarzeń między wieloma instancjami serwera
- Filtry wyjątków wymagają implementacji specyficznych dla WebSocket przy użyciu
WsExceptioni niestandardowych filtrów
Zacznij ćwiczyć!
Sprawdź swoją wiedzę z naszymi symulatorami rozmów i testami technicznymi.

Autor:
Anthony Fillion-MailletProgramista fullstack, założyciel SharpSkill
Programista fullstack od ponad 10 lat. Prowadzi SharpSkill i odpowiada za wszystko, co się tu ukazuje.
Zaktualizowano 10 sierpnia 2026
Tagi
Udostępnij
Powiązane artykuły

NestJS i GraphQL w 2026: Schematy, Resolvery i Pytania Rekrutacyjne
Kompletny poradnik NestJS GraphQL omawiający podejścia schema-first i code-first, resolvery, DataLoader oraz pytania rekrutacyjne w 2026 roku.

Rozmowa NestJS: Guards, Interceptory i architektura modułowa
Częste pytania na rozmowach technicznych z NestJS dotyczące Guards, Interceptorów i architektury modułowej, z konkretnymi przykładami kodu w TypeScript i wyjaśnieniami technicznymi.

NestJS + Prisma: nowoczesny stack backendowy dla Node.js
Kompletny przewodnik po budowaniu nowoczesnego API backendowego z NestJS i Prismą. Konfiguracja, modele, serwisy, transakcje i dobre praktyki.