Episode ini membangun aplikasi real-time pertama: chat sederhana dengan server ws, UI HTML, join dan leave notification, daftar pengguna online, dan debugging lewat DevTools.

Sekarang tiba saatnya merangkai semua yang sudah dipelajari menjadi satu: aplikasi real-time pertama. Kita membangun chat sederhana dengan server ws di Node.js, antarmuka HTML, daftar pengguna online, dan notifikasi join dan leave.
Episode 7 bukan hanya menulis kode — kalian juga belajar mendebug aplikasi real-time lewat DevTools: memeriksa frame WebSocket, memantau state koneksi, dan melacak pesan. Di akhir episode kalian memiliki aplikasi yang bisa dibuka di beberapa tab sekaligus dan melihat pesan berjalan antar tab secara real-time.
chat-app/
server.js
public/
index.html
style.css
app.jsLayout chat-app/server.js + public/ di atas memisahkan logika server dan aset klien. Server melayani file statis sekaligus WebSocket di port yang sama — pola yang sudah diperkenalkan di episode 5.
Server perlu tahu siapa pengirim setiap pesan. Kita simpan nama pengguna sebagai properti objek WebSocket:
const http = require("http");
const fs = require("fs");
const path = require("path");
const { WebSocketServer } = require("ws");
const server = http.createServer((req, res) => {
const file = path.join(__dirname, "public", req.url === "/" ? "index.html" : req.url);
fs.createReadStream(file).pipe(res);
});
const wss = new WebSocketServer({ server });
wss.on("connection", (ws) => {
ws.on("message", (data) => {
const pesan = JSON.parse(data.toString());
if (pesan.type === "join") {
ws.nama = pesan.nama;
broadcast({ type: "sistem", teks: pesan.nama + " bergabung" });
kirimDaftar();
}
if (pesan.type === "chat") {
broadcast({ type: "chat", nama: ws.nama, teks: pesan.teks });
}
});
ws.on("close", () => {
if (ws.nama) {
broadcast({ type: "sistem", teks: ws.nama + " keluar" });
kirimDaftar();
}
});
});Menyimpan ws.nama langsung ke objek koneksi membuat identitas melekat tanpa struktur data eksternal. Semua pesan dibungkus JSON dengan field type sebagai penanda — pola envelope yang akan kita dalami di episode 10.
function broadcast(pesan) {
for (const klien of wss.clients) {
klien.send(JSON.stringify(pesan));
}
}
function kirimDaftar() {
const daftar = [];
for (const klien of wss.clients) {
daftar.push(klien.nama);
}
broadcast({ type: "daftar", daftar });
}wss.clients adalah Set bawaan ws berisi semua koneksi aktif — tidak perlu Map manual seperti episode 5. broadcast mengirim objek yang sudah diserialisasi dengan JSON.stringify(pesan).
Halaman chat punya tiga bagian: daftar pengguna, daftar pesan, dan kotak pengiriman.
<div id="daftar"></div>
<div id="pesan"></div>
<input id="input" placeholder="ketik pesan">
<button id="kirim">Kirim</button>Struktur di atas memisahkan daftar pengguna online, daftar pesan, dan kontrol input — semuanya diisi dari JavaScript.
const input = document.getElementById("input");
const ws = new WebSocket("ws://localhost:8080");
const nama = prompt("Nama kamu?");
ws.onopen = () => {
ws.send(JSON.stringify({ type: "join", nama }));
};
ws.onmessage = (event) => {
const pesan = JSON.parse(event.data);
if (pesan.type === "daftar") {
renderDaftar(pesan.daftar);
} else {
renderPesan(pesan);
}
};
function kirim() {
ws.send(JSON.stringify({ type: "chat", teks: input.value }));
input.value = "";
}ws.onopen memastikan pesan join dikirim tepat setelah koneksi terbuka. ws.onmessage memecah satu handler menjadi dua jalur berdasarkan pesan.type.
Notifikasi sistem seperti "user bergabung" dan "user keluar" muncul dari pesan bertipe sistem yang dikirim server di event connection dan close. Klien cukup merender teksnya dengan gaya berbeda dari pesan chat biasa.
waktu saat membungkus pesan, dikirim bersama payload.typing saat mengetik; server menyiarkannya ke klien lain tanpa menyimpannya.Buka DevTools di tab Network, pilih filter WS, dan klik koneksi WebSocket. Panel detail menampilkan Messages — setiap frame yang dikirim dan diterima, lengkap dengan timestamp dan arahnya.
out {type: "join", nama: "arman"}
in {type: "sistem", teks: "arman bergabung"}
out {type: "chat", teks: "halo semua"}
in {type: "chat", nama: "arman", teks: "halo semua"}Melihat arah frame out dan in di atas membuat alur pesan jelas. Ini alat debugging utama untuk aplikasi WebSocket — biasakan membukanya setiap kali pesan tidak sampai.
kirimDaftar.Episode 7 menyatukan klien dan server menjadi aplikasi chat yang nyata: identitas pengguna, broadcast, join dan leave notification, daftar online, serta kemampuan debugging frame lewat DevTools.
Inti yang harus dibawa pulang:
Di episode 8 selanjutnya kita mengamankan aplikasi ini: authentication dan authorization — strategi JWT dan session, autentikasi saat handshake, middleware Socket.IO, kontrol akses room, serta praktik terbaik keamanan.