Server-Sent Events di Node.js: Real-Time Update tanpa WebSocket
Real-time communication sering diasosiasikan dengan WebSocket, tetapi protokol tersebut tidak selalu menjadi pilihan paling efisien. Server-Sent Events (SSE) menyediakan alternatif yang lebih sederhana untuk kasus di mana data mengalir secara one-way: dari server ke client. SSE menggunakan koneksi HTTP persistent dan standard EventSource API yang sudah built-in di browser modern.
Kelebihan utama SSE terletak pada kompleksitas yang minimal. Tidak perlu library tambahan di client, reconnect otomatis sudah ditangani oleh browser, dan SSE bekerja melalui HTTP biasa sehingga kompatibel dengan caching, load balancing, dan firewall yang mungkin memblokir WebSocket. Keterbatasannya hanya satu: komunikasi bersifat unidirectional dari server ke client.
Apa itu Server-Sent Events
SSE adalah mekanisme streaming berbasis HTTP yang memungkinkan server mengirimkan update ke client secara berkelanjutan. Format data mengikuti spesifikasi text/event-stream dengan struktur sederhana: setiap event diawali dengan prefix data: dan diakhiri dengan dua baris newline.
Perbedaan fundamental antara SSE dan WebSocket:
- SSE: One-way (server → client), berbasis HTTP, reconnect otomatis, lebih mudah di-debug.
- WebSocket: Two-way (full-duplex), memerlukan protokol upgrade, ideal untuk chat atau game multiplayer.
Untuk use case seperti live notification, stock ticker, atau progress update, SSE seringkali lebih than sufficient tanpa overhead WebSocket.
Implementasi SSE dengan Native HTTP Module
Node.js dapat menangani SSE menggunakan modul http tanpa dependency tambahan. Konfigurasi header Content-Type: text/event-stream dan Connection: keep-alive merupakan requirement agar browser mengenali respons sebagai event stream.
const http = require('http');
const server = http.createServer((req, res) => {
if (req.url === '/events') {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Access-Control-Allow-Origin': '*'
});
const sendEvent = (data) => {
res.write(`data: ${JSON.stringify(data)}\n\n`);
};
// Kirim event setiap 3 detik
const interval = setInterval(() => {
sendEvent({
timestamp: new Date().toISOString(),
message: 'Update dari server'
});
}, 3000);
// Bersihkan interval saat client disconnect
req.on('close', () => {
clearInterval(interval);
res.end();
});
} else {
res.writeHead(404);
res.end('Not Found');
}
});
server.listen(3000, () => {
console.log('SSE server berjalan di port 3000');
});Server di atas membuka endpoint /events yang mengirimkan JSON payload setiap 3 detik. Handler req.on('close') memastikan resources dibersihkan ketika client menutup koneksi — hal ini penting untuk mencegah memory leak pada aplikasi production.
Integrasi SSE dengan Express.js
MERN Stack Development
Launch your journey into full-stack web development with this comprehensive, pro...
Dalam project nyata, Express.js lebih umum digunakan untuk routing dan middleware. Integrasi SSE ke Express tidak berbeda jauh dengan native HTTP, hanya ditambahkan helper untuk mengirim event dengan format yang konsisten.
const express = require('express');
const app = express();
app.get('/events', (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
const sendEvent = (event, data) => {
res.write(`event: ${event}\n`);
res.write(`data: ${JSON.stringify(data)}\n\n`);
};
// Kirim event khusus untuk inisialisasi koneksi
sendEvent('connected', { status: 'SSE connection established' });
// Simulasi push notification
const notificationInterval = setInterval(() => {
sendEvent('notification', {
id: Date.now(),
text: 'Notifikasi baru diterima'
});
}, 5000);
req.on('close', () => {
clearInterval(notificationInterval);
console.log('Client disconnected');
});
});
app.listen(3000, () => {
console.log('Express SSE server berjalan di port 3000');
});Express handler ini menambahkan field event pada payload, memungkinkan client untuk mendengarkan event spesifik menggunakan addEventListener daripada handler onmessage generik. Pola ini berguna ketika server mengirimkan berbagai jenis update — misalnya, event notification untuk alert dan event progress untuk tracking upload.
Client-Side Implementation dan Reconnect Handling
Browser modern menyediakan EventSource API yang mengelola koneksi SSE secara native. Fitur reconnect otomatis sudah built-in: jika koneksi terputus, browser akan mencoba reconnect dengan exponential backoff. Kita juga dapat menangani event khusus yang didefinisikan oleh server.
const eventSource = new EventSource('http://localhost:3000/events');
// Handler untuk event default (tanpa field 'event:')
eventSource.onmessage = (e) => {
const data = JSON.parse(e.data);
console.log('Pesan diterima:', data);
};
// Handler untuk event spesifik 'notification'
eventSource.addEventListener('notification', (e) => {
const payload = JSON.parse(e.data);
displayNotification(payload.text);
});
eventSource.addEventListener('connected', (e) => {
console.log('Status koneksi:', JSON.parse(e.data).status);
});
eventSource.onerror = (err) => {
console.error('SSE error:', err);
// Browser akan otomatis mencoba reconnect
};
// Tutup koneksi saat komponen unmount (misal di React)
// eventSource.close();Reconnect behavior pada EventSource mengikuti spesifikasi HTML5: browser akan menunggu beberapa detik sebelum retry, dan delay akan bertambah secara eksponensial hingga batas maksimum. Server dapat mengontrol retry interval dengan mengirimkan field retry: dalam event stream. Untuk aplikasi production, pertimbangkan juga untuk mengimplementasikan Last-Event-ID header agar client tidak kehilangan event selama disconnect.
Kapan Menggunakan SSE dibandingkan WebSocket
Pemilihan antara SSE dan WebSocket bergantung pada arah komunikasi dan kompleksitas requirement.
Pilih SSE ketika:
- Data hanya mengalir dari server ke client (one-way).
- Aplikasi berjalan di belakang firewall atau proxy yang membatasi WebSocket.
- Diperlukan reconnect otomatis tanpa menulis logic tambahan.
- Use case meliputi: live dashboard, news feed, log streaming, atau stock price ticker.
Pilih WebSocket ketika:
- Diperlukan komunikasi two-way real-time seperti chat atau collaborative editing.
- Latency harus se-minimal mungkin dengan overhead handshake yang lebih sedikit.
- Aplikasi memerlukan binary data transfer.
SSE adalah solusi pragmatic untuk banyak scenario real-time. Kombinasi SSE di frontend dengan Redis Pub/Sub di backend memungkinkan arsitektur push notification yang scalable tanpa memperkenalkan kompleksitas WebSocket cluster.
Mau memperdalam skill Web Development secara sistematis? Bergabunglah dengan Web Development Bootcamp di Rumah Coding. Kurikulum praktis dengan proyek real-world dan mentorship dari praktisi industri.
Course Terkait
MERN Stack Development
Launch your journey into full-stack web development with this comprehensive, project-driven course. Designed for beginners, this course demystifies the MERN stack (MongoDB, Express.js, React.js, Node.js) by guiding you step-by-step in building a real-world application from scratch. By the end of this course, you will have the practical skills and a complete portfolio project to confidently step into the modern web development industry.
EduStream - Mini Learning Management System (LMS)
- Secure Authentication & Authorization: Robust user registration and login using JWT, with strict role-based access control (Admin/Instructor vs. Student).
- Course Management (Admin Dashboard): Full CRUD (Create, Read, Update, Delete) capabilities for administrators to manage course details, including titles, descriptions, pricing, and thumbnail image uploads.
- Public Course Catalog: An interactive and responsive storefront where users can browse available courses.