Building Real-time Applications with Socket.io

Socket.io adalah library JavaScript yang memungkinkan komunikasi real-time, dua arah, dan berbasis event antara browser dan server. Dalam tutorial ini, kita akan membangun aplikasi chat real-time sederhana.

Prasyarat

  • Node.js (versi 14+)
  • npm atau yarn
  • Basic JavaScript knowledge

Setup Project

mkdir socket-chat-app
cd socket-chat-app
npm init -y
npm install express socket.io

Basic Server Setup

Buat file server.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);

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
});

io.on('connection', (socket) => {
  console.log('User connected:', socket.id);
  
  socket.on('disconnect', () => {
    console.log('User disconnected:', socket.id);
  });
});

server.listen(3000, () => {
  console.log('Server running on port 3000');
});

Client Implementation

Buat file index.html:

<!DOCTYPE html>
<html>
<head>
  <title>Socket.io Chat</title>
  <style>
    body { font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; }
    #messages { list-style-type: none; padding: 0; height: 400px; overflow-y: scroll; border: 1px solid #ddd; margin-bottom: 20px; }
    #messages li { padding: 10px; border-bottom: 1px solid #eee; }
    #form { display: flex; gap: 10px; }
    #input { flex: 1; padding: 10px; }
    button { padding: 10px 20px; background: #007bff; color: white; border: none; cursor: pointer; }
  </style>
</head>
<body>
  <ul id="messages"></ul>
  <form id="form" action="">
    <input id="input" autocomplete="off" placeholder="Type a message..." />
    <button>Send</button>
  </form>

  <script src="/socket.io/socket.io.js"></script>
  <script>
    const socket = io();
    const form = document.getElementById('form');
    const input = document.getElementById('input');
    const messages = document.getElementById('messages');

    form.addEventListener('submit', (e) => {
      e.preventDefault();
      if (input.value) {
        socket.emit('chat message', input.value);
        input.value = '';
      }
    });

    socket.on('chat message', (msg) => {
      const item = document.createElement('li');
      item.textContent = msg;
      messages.appendChild(item);
      messages.scrollTop = messages.scrollHeight;
    });
  </script>
</body>
</html>

Handling Messages

Update server.js untuk handle messages:

io.on('connection', (socket) => {
  console.log('User connected:', socket.id);
  
  // Broadcast message to all clients
  socket.on('chat message', (msg) => {
    io.emit('chat message', msg);
  });
  
  socket.on('disconnect', () => {
    console.log('User disconnected:', socket.id);
  });
});

Advanced Features

1. Rooms

Rooms memungkinkan Anda membuat channel terpisah:

// Join room
socket.join('room1');

// Emit to specific room
io.to('room1').emit('message', 'Hello room1!');

// Leave room
socket.leave('room1');

2. Namespaces

Namespaces untuk memisahkan concern:

const chatNamespace = io.of('/chat');
const notificationNamespace = io.of('/notifications');

chatNamespace.on('connection', (socket) => {
  console.log('User connected to chat');
});

3. Middleware

Autentikasi dengan middleware:

io.use((socket, next) => {
  const token = socket.handshake.auth.token;
  if (isValidToken(token)) {
    next();
  } else {
    next(new Error('Authentication error'));
  }
});

Best Practices

  1. Error Handling

    socket.on('error', (error) => {
      console.error('Socket error:', error);
    });
  2. Reconnect Logic

    const socket = io({
      reconnection: true,
      reconnectionAttempts: 5,
      reconnectionDelay: 1000,
    });
  3. Room Cleanup

    socket.on('disconnect', () => {
      socket.rooms.forEach((room) => {
        socket.leave(room);
      });
    });

Deployment Considerations

Saat deploy ke production, pertimbangkan:

  • Sticky Sessions: Required untuk multi-server setup
  • Redis Adapter: Untuk scaling ke multiple server
  • Load Balancer: Configure untuk support WebSocket
const { createAdapter } = require('@socket.io/redis-adapter');
const { createClient } = require('redis');

const pubClient = createClient({ url: 'redis://localhost:6379' });
const subClient = pubClient.duplicate();

io.adapter(createAdapter(pubClient, subClient));

Kesimpulan

Socket.io membangun fondasi yang kuat untuk aplikasi real-time. Dengan fitur seperti rooms, namespaces, dan middleware, Anda dapat membangun aplikasi yang scalable dan maintainable.

Selanjutnya, coba eksplorasi:

  • File sharing dengan Socket.io
  • Video call dengan WebRTC + Socket.io
  • Collaborative editing