Як інтегрувати WebSocket з Express.js?
WebSocket в Express.js
WebSocket забезпечує повнодуплексні, постійні з'єднання між клієнтом і сервером. На відміну від HTTP (запит-відповідь), WebSocket дозволяє серверу відправляти дані клієнтам у реальному часі.
HTTP vs WebSocket
| Особливість | HTTP | WebSocket |
|---|---|---|
| З'єднання | Нове для кожного запиту | Постійне |
| Напрямок | Клієнт → Сервер | Двостороннє |
| Протокол | http:// / https:// | ws:// / wss:// |
| Накладні витрати | Заголовки на кожен запит | Мінімальні після рукопожаття |
| Сценарій використання | REST API, сторінки | Реальний час: чат, сповіщення, ігри |
Використання Socket.IO (Найпопулярніше)
bash
npm install socket.ioНалаштування сервера
js
const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: 'http://localhost:3000',
methods: ['GET', 'POST']
}
});
io.on('connection', (socket) => {
console.log('Користувач підключився:', socket.id);
// Слухати події
socket.on('chat:message', (data) => {
// Транслювати всім, окрім відправника
socket.broadcast.emit('chat:message', {
user: data.user,
text: data.text,
timestamp: new Date()
});
});
// Приєднатися до кімнати
socket.on('room:join', (roomId) => {
socket.join(roomId);
io.to(roomId).emit('room:userJoined', socket.id);
});
socket.on('disconnect', () => {
console.log('Користувач відключився:', socket.id);
});
});
// Маршрути Express все ще працюють нормально
app.get('/api/health', (req, res) => res.json({ status: 'ok' }));
server.listen(4000, () => console.log('Сервер на порту 4000'));Клієнт
js
import { io } from 'socket.io-client';
const socket = io('http://localhost:4000');
socket.on('connect', () => {
console.log('Підключено:', socket.id);
});
socket.emit('chat:message', { user: 'John', text: 'Привіт!' });
socket.on('chat:message', (data) => {
console.log(`${data.user}: ${data.text}`);
});Використання рідної бібліотеки ws (Легка)
bash
npm install wsjs
const express = require('express');
const { WebSocketServer } = require('ws');
const app = express();
const server = app.listen(4000);
const wss = new WebSocketServer({ server });
wss.on('connection', (ws) => {
ws.on('message', (message) => {
const data = JSON.parse(message);
// Транслювати всім підключеним клієнтам
wss.clients.forEach((client) => {
if (client.readyState === 1) {
client.send(JSON.stringify(data));
}
});
});
});Кімнати та простори (Socket.IO)
js
// Простір для адмін-панелі
const adminIO = io.of('/admin');
adminIO.on('connection', (socket) => {
// Тільки події адміністратора тут
socket.on('admin:action', handleAdminAction);
});
// Кімнати в межах стандартного простору
io.on('connection', (socket) => {
socket.on('joinRoom', (roomId) => {
socket.join(roomId);
});
socket.on('message', (data) => {
io.to(data.roomId).emit('message', data);
});
});Аутентифікація
js
io.use((socket, next) => {
const token = socket.handshake.auth.token;
try {
const user = jwt.verify(token, process.env.JWT_SECRET);
socket.user = user;
next();
} catch (err) {
next(new Error('Помилка аутентифікації'));
}
});Socket.IO vs ws
| Особливість | Socket.IO | ws |
|---|---|---|
| Розмір | ~50KB | ~3KB |
| Кімнати | Вбудовані | Вручну |
| Резервне копіювання | HTTP опитування | Тільки WebSocket |
| Авто-перепідключення | Вбудоване | Вручну |
| Простори | Вбудовані | Немає |
| Бінарний | Так | Так |
Порада: Використовуйте Socket.IO для складних реальних додатків (чат, співпраця, сповіщення). Використовуйте ws для простих, з низькими накладними витратами WebSocket з'єднань. Обидва можуть співіснувати з маршрутами Express на одному сервері.
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.