W erze aplikacji webowych wymagających natychmiastowej interakcji, takich jak czaty, gry online czy systemy monitoringu, WebSockets stały się kluczową technologią. Node.js, dzięki swojej asynchronicznej naturze i lekkości, jest idealnym środowiskiem do budowania takich rozwiązań. W tym artykule omówimy podstawy WebSockets, porównamy popularne biblioteki, pokażemy przykłady kodu oraz najlepsze praktyki. Bazujemy na aktualnych rekomendacjach z 2024 i 2025 roku, w tym na wbudowanym wsparciu Node.js od wersji 21.
Czym są WebSockets i dlaczego warto je używać w Node.js?
WebSockets to protokół komunikacji, który umożliwia dwukierunkową, pełnodupleksową wymianę danych między klientem a serwerem poprzez pojedyncze, trwałe połączenie. W przeciwieństwie do HTTP, gdzie każde żądanie wymaga nowego połączenia, WebSockets pozwalają na ciągły strumień danych z niskim opóźnieniem, co jest kluczowe dla aplikacji real-time.
Node.js doskonale nadaje się do tego celu dzięki modelowi event-driven i non-blocking I/O. Od wersji 21 Node.js oferuje wbudowane wsparcie dla klienta WebSocket (stabilne od v22.4.0), ale do serwera nadal polecane są biblioteki zewnętrzne. Popularne to:
- ws: Lekka, szybka biblioteka implementująca czysty protokół WebSocket. Idealna do prostych zastosowań, bez dodatkowych overheadów.
- Socket.IO: Rozszerza WebSockets o funkcje jak fallback na HTTP long-polling, automatyczne ponowne połączenia, acknowledgements, broadcasting i multiplexing (namespaces). Dodaje nieco overheadu (kilka bajtów na wiadomość), ale ułatwia rozwój złożonych aplikacji. Nie jest kompatybilna z czystymi WebSockets.
Wybór zależy od potrzeb: ws dla wydajności, Socket.IO dla wygody i skalowalności.
Podstawowa konfiguracja serwera WebSocket
Zacznijmy od instalacji: npm install ws lub npm install socket.io.
Przykład z biblioteką ws
Prosty serwer broadcastujący wiadomości do wszystkich klientów:
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
ws.send('Witaj na serwerze WebSocket!');
ws.on('message', (message) => {
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(`Serwer otrzymał: ${message}`);
}
});
});
ws.on('close', () => console.log('Klient rozłączony'));
});Klient w przeglądarce:
const ws = new WebSocket('ws://localhost:8080');
ws.onopen = () => ws.send('Cześć, serwerze!');
ws.onmessage = (event) => console.log(`Wiadomość z serwera: ${event.data}`);
ws.onclose = () => console.log('Połączenie zamknięte');Ten kod umożliwia broadcasting i obsługę rozłączeń.
Przykład z Socket.IO
Serwer:
const { Server } = require("socket.io");
const io = new Server(8000);
io.on("connection", (socket) => {
console.log("Użytkownik połączony");
socket.on("wiadomosc", (data) => {
io.emit("wiadomosc", data); // Broadcasting do wszystkich
});
});Klient:
const io = require("socket.io-client");
const socket = io("http://localhost:8000");
socket.on("connect", () => {
console.log("Połączono");
socket.emit("wiadomosc", "Cześć!");
});
socket.on("wiadomosc", (data) => console.log(data));Socket.IO dodaje funkcje jak acknowledgements: socket.emit("wiadomosc", data, (ack) => { /* potwierdzenie */ });.
Przykładowa aplikacja: Czat real-time
Budujemy prosty czat z wieloma klientami. Użyjemy ws dla serwera i HTML/JS dla klienta.
Serwer (server.js):
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const port = 6969;
const server = http.createServer(express);
const wss = new WebSocket.Server({ server });
wss.on('connection', (ws) => {
ws.on('message', (data) => {
wss.clients.forEach((client) => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
});
});
server.listen(port, () => console.log(`Serwer nasłuchuje na porcie ${port}!`));Klient (index.html):
<h1>Czat Real-Time</h1>
<pre id="messages" style="height: 400px; overflow: scroll"></pre>
<input type="text" id="messageBox" placeholder="Wpisz wiadomość" style="display: block; width: 100%; margin-bottom: 10px; padding: 10px;" />
<button id="send" style="width: 100%; height: 30px;">Wyślij</button>
<script>
const sendBtn = document.querySelector('#send');
const messages = document.querySelector('#messages');
const messageBox = document.querySelector('#messageBox');
let ws;
function showMessage(message) {
messages.textContent += `\n\n${message}`;
messages.scrollTop = messages.scrollHeight;
messageBox.value = '';
}
function init() {
ws = new WebSocket('ws://localhost:6969');
ws.onopen = () => console.log('Połączono!');
ws.onmessage = ({ data }) => showMessage(data);
ws.onclose = () => ws = null;
}
sendBtn.onclick = () => {
if (!ws) return showMessage("Brak połączenia :(");
ws.send(messageBox.value);
showMessage(messageBox.value);
}
init();
</script>Ten przykład umożliwia wysyłanie wiadomości między wieloma klientami w czasie rzeczywistym.
Najlepsze praktyki
- Bezpieczeństwo: Używaj WSS (z SSL) zamiast WS. Implementuj autentykację JWT w nagłówkach. Odświeżaj połączenia co godzinę dla odnowienia tokenów.
- Skalowalność: Monitoruj liczbę otwartych połączeń, nie tylko CPU. Używaj brokerów wiadomości (Redis, Kafka) z Pub/Sub dla multi-node. Dostosuj ustawienia OS dla wielu połączeń.
- Monitorowanie: Implementuj heartbeat (ping/pong co 30s) do wykrywania zerwanych połączeń. Używaj APM jak Elastic czy New Relic z custom transactions.
- Inne: Obsługuj błędy, optymalizuj rozmiar wiadomości, używaj kompresji. Dla automatycznego reconnection – Socket.IO ma to wbudowane, dla ws implementuj ręcznie.
Wniosek
WebSockets w Node.js otwierają drzwi do dynamicznych aplikacji real-time. Zaczynając od prostych przykładów, możesz skalować do złożonych systemów. Pamiętaj o aktualizacjach Node.js i testowaniu w produkcji. Śledź dokumentację i community dla nowych trendów.
Citations:
- Built-in WebSockets in Node.js 2024: A Comprehensive Guide
- Node.js WebSocket Tutorial — Real-Time Chat Room
- WebSockets on production with Node.js
- Introduction | Socket.IO
- Node.js — Node.js WebSocket
- WebSocket vs Socket.IO: Performance & Use Case Guide
- Node.js and Websockets best practices checklist
- websockets/ws: Simple to use, blazing fast
- Websocket: Best Practices
- WebSocket vs Ws vs Socket.io