Episode ini membangun server WebSocket dengan library ws: instalasi, pembuatan server, event connection dan message, broadcast ke semua klien, serta manajemen koneksi dengan identifikasi dan pembersihan.

Di episode 4 kalian punya klien. Sekarang waktunya membangun sisi yang melayani: server WebSocket. Kita memakai ws, library Node.js paling populer untuk protokol ini.
Library ws ringan dan mendekati protokol asli — tidak ada lapisan reconnection otomatis atau room. Justru itu kelebihannya: kalian akan memahami cara kerja WebSocket yang sebenarnya sebelum melapisinya dengan kemudahan Socket.IO di episode 6. Di episode ini kalian akan membuat server, menangani event, broadcast pesan, dan mengelola banyak klien.
Mulai dari project kosong:
mkdir ws-server
cd ws-server
npm init -y
npm install wsPerintah npm install ws menarik library beserta dependency-nya yang minim. Setelah ini, kalian siap menulis server pertama.
const { WebSocketServer } = require("ws");
const wss = new WebSocketServer({ port: 8080 });
wss.on("connection", (ws) => {
console.log("klien terhubung");
ws.send("selamat datang");
});new WebSocketServer({ port: 8080 }) membuat server yang mendengarkan koneksi di port 8080. Event connection dipanggil setiap kali handshake selesai, membawa objek ws milik klien tersebut.
Server berkomunikasi lewat event. Berikut handler yang wajib kalian kenal:
wss.on("connection", (ws) => {
ws.on("message", (data, isBinary) => {
console.log("terima:", data.toString());
ws.send("pesan diterima");
});
ws.on("close", () => {
console.log("klien pergi");
});
ws.on("error", (err) => {
console.error("error:", err.message);
});
ws.on("pong", () => {
console.log("pong diterima");
});
});ws.on("message", handler) dipanggil untuk setiap frame data. Argumen isBinary membedakan text dan binary frame. Event pong hanya aktif jika server memakai heartbeat — dibahas di episode 11.
Karena ws bisa menerima dua tipe data:
ws.on("message", (data, isBinary) => {
if (isBinary) {
console.log("data biner:", data);
} else {
console.log("teks:", data.toString());
}
});Cek isBinary menentukan cara menafsirkan data, yang di ws berupa Buffer untuk binary dan Buffer atau string untuk text.
Untuk mengirim ke klien tertentu, kalian perlu menyimpan referensinya:
const wss = new WebSocketServer({ port: 8080 });
const klien = new Map();
wss.on("connection", (ws) => {
klien.set(ws, new Date());
ws.on("message", (data) => {
const pesan = data.toString();
for (const [k] of klien) {
k.send(pesan);
}
});
});Mengulang for (const [k] of klien) dan memanggil k.send(pesan) pada semua entri adalah broadcast manual. Karena tidak ada API broadcast di ws, kalian membangunnya sendiri — persis yang akan dipermudah Socket.IO.
Tanpa pembersihan, klien yang sudah putus akan tetap menganggur di memori:
ws.on("close", () => {
klien.delete(ws);
console.log("klien tersisa:", klien.size);
});Selalu panggil klien.delete(ws) di event close. Ukuran klien.size juga berguna sebagai metrik jumlah koneksi aktif — cikal bakal monitoring di episode 18.
WebSocketServer menerima berbagai opsi:
port atau server: port mandiri atau server HTTP yang sudah ada.maxPayload: batas ukuran payload, misalnya 100e6 untuk 100MB.perMessageDeflate: mengaktifkan kompresi permessage-deflate.clientTracking: melacak daftar klien di wss.clients.Menggabungkan dengan server HTTP memberi keuntungan besar: satu port melayani API REST dan WebSocket.
const http = require("http");
const { WebSocketServer } = require("ws");
const server = http.createServer((req, res) => {
res.writeHead(200);
res.end("server jalan");
});
const wss = new WebSocketServer({ server });
wss.on("connection", (ws) => {
ws.send("halo dari port yang sama");
});
server.listen(8080);Dengan new WebSocketServer({ server }), satu server HTTP di port 8080 melayani keduanya. Inilah pola yang dipakai aplikasi production.
Tip
Setel maxPayload selalu. Tanpa batas, klien bisa mengirim payload raksasa dan memakan memori server — salah satu celah DoS yang akan kita bahas di episode 19.
Episode 5 memberi kalian server WebSocket yang fungsional: instalasi ws, pembuatan server, handling event connection dan message, unicast dan broadcast manual, serta manajemen daftar klien yang bersih dari kebocoran memori.
Inti yang harus dibawa pulang:
Di episode 6 selanjutnya kita memperkenalkan Socket.IO — library yang melapisi WebSocket dengan reconnection otomatis, fallback, room, dan namespace. Kalian akan melihat kapan memakai Socket.IO dan kapan tetap memakai ws murni.