Mengimplementasikan WebSocket di ElysiaJS: setup endpoint WebSocket dengan onMessage, onOpen, onClose, typed messages menggunakan TypeBox, broadcast, dan room management untuk aplikasi real-time.

Setelah di episode 13 kita mengimplementasikan OAuth social login, pada episode ini kita akan memahami WebSocket — protokol komunikasi real-time yang memungkinkan server mengirim data ke client tanpa diminta. WebSocket adalah fondasi untuk chat apps, live notifications, collaborative editing, dan game state sync.
import { Elysia } from 'elysia'
const app = new Elysia()
.ws('/ws', {
open: (ws) => {
console.log('Client connected')
ws.send({ type: 'welcome', message: 'Connected!' })
},
message: (ws, message) => {
console.log('Received:', message)
ws.send({ type: 'echo', data: message })
},
close: (ws) => {
console.log('Client disconnected')
},
})
.listen(3000)const ws = new WebSocket('ws://localhost:3000/ws')
ws.onopen = () => {
ws.send(JSON.stringify({ type: 'chat', message: 'Hello!' }))
}
ws.onmessage = (event) => {
console.log('Server:', JSON.parse(event.data))
}Gunakan TypeBox untuk mendefinisikan tipe pesan:
import { Elysia, t } from 'elysia'
const app = new Elysia()
.ws('/ws', {
schema: {
body: t.Object({
type: t.Union([
t.Literal('chat'),
t.Literal('join'),
t.Literal('leave'),
]),
message: t.String(),
room: t.Optional(t.String()),
}),
},
message: (ws, { type, message, room }) => {
// type, message, room otomatis typed
if (type === 'chat') {
ws.send({ type: 'chat', message })
}
},
}).ws('/ws', {
message: (ws, message) => {
// Kirim ke semua kecuali sender
ws.send(message) // kirim ke sender
},
open: (ws) => {
ws.send({ type: 'info', message: 'Welcome!' })
},
})Untuk chat atau notification per-room, gunakan pub/sub pattern:
const rooms = new Map<string, Set<any>>()
const app = new Elysia()
.ws('/ws', {
open: (ws) => {
const room = 'general'
if (!rooms.has(room)) rooms.set(room, new Set())
rooms.get(room)!.add(ws)
},
message: (ws, { room, message }) => {
const clients = rooms.get(room)
if (clients) {
for (const client of clients) {
client.send({ type: 'chat', message })
}
}
},
close: (ws) => {
for (const [room, clients] of rooms) {
clients.delete(ws)
if (clients.size === 0) rooms.delete(room)
}
},
})Note
WebSocket menggunakan koneksi persistent, berbeda dari HTTP request-response. Untuk production, pertimbangkan menggunakan adapter seperti Redis untuk horizontal scaling di multiple instances.
Pada episode 14 ini, kalian telah memahami WebSocket di ElysiaJS — dari setup endpoint hingga typed messages dan room management.
Inti yang harus dibawa pulang:
app.ws() mendefinisikan WebSocket endpoint.open, message, close adalah lifecycle handler WebSocket.Di episode 15 selanjutnya kita akan memahami OpenAPI dan API documentation — auto-generate Swagger UI, customizing metadata, dan export OpenAPI spec. Sampai jumpa di episode 15!