WebSocket With Server-Sent Event (SSE) in Express.js

Real-time communication is a cornerstone of modern web applications, enabling functionalities like live updates, chat systems, notifications, and collaborative tools. Two popular techniques to implement real-time data transmission in Express.js are WebSocket and Server-Sent Events (SSE). This chapter will dive deep into both technologies, explaining their use cases, differences, implementations, and advanced strategies.

Introduction to Real-Time Communication

Real-time communication allows a server to push updates to a client without requiring the client to repeatedly request data. This is essential for applications like:

  • Chat Applications
  • Live Score Updates
  • Stock Market Feeds
  • Collaborative Editing

Traditional HTTP vs. Real-Time Protocols

AspectHTTP (Request-Response)WebSocketSSE
DirectionClient → ServerBi-directionalServer → Client
ConnectionNew connection per requestPersistentPersistent
ProtocolHTTPWebSocketHTTP
ComplexitySimpleComplexSimple
Use CaseStatic APIsChat systems, gamesNotifications, live updates

What is WebSocket?

Overview

WebSocket is a protocol that provides full-duplex communication between a client and server over a single TCP connection. It enables both the client and the server to send messages to each other simultaneously.

How WebSocket Works

  1. Handshake: Starts as an HTTP request and upgrades to WebSocket.
  2. Persistent Connection: A single connection is kept open.
  3. Message Exchange: Data can flow freely in both directions.

Use Cases

  • Chat applications
  • Multiplayer games
  • Real-time dashboards

What is Server-Sent Events (SSE)?

Overview

Server-Sent Events (SSE) is a simpler way to push updates from the server to the client using HTTP. Unlike WebSocket, SSE only allows unidirectional communication (server to client).

How SSE Works

  1. The client makes an HTTP request to the server.
  2. The server keeps the connection open and sends updates as new events.
  3. The client listens to these events using the EventSource API.

Use Cases

  • Live notifications
  • Real-time feeds
  • Progress updates

Setting Up WebSocket in Express.js

Install Dependencies

				
					npm install express ws

				
			

WebSocket Server with Express.js

				
					const express = require('express');
const { WebSocketServer } = require('ws');

const app = express();
const PORT = 3000;

// HTTP Server
app.get('/', (req, res) => {
  res.send('WebSocket with Express.js');
});

// WebSocket Server
const wss = new WebSocketServer({ noServer: true });

// WebSocket Connection
wss.on('connection', (ws) => {
  console.log('Client connected');
  
  // Listen for messages from the client
  ws.on('message', (message) => {
    console.log(`Received: ${message}`);
    ws.send(`You said: ${message}`);
  });

  // Handle connection close
  ws.on('close', () => {
    console.log('Client disconnected');
  });
});

// Upgrade HTTP to WebSocket
const server = app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});

server.on('upgrade', (request, socket, head) => {
  wss.handleUpgrade(request, socket, head, (ws) => {
    wss.emit('connection', ws, request);
  });
});

				
			

Explanation

  1. WebSocket Server: Uses ws library for WebSocket functionality.
  2. Upgrade: Upgrades HTTP requests to WebSocket connections.
  3. Message Handling: The server listens to and responds to client messages.

Testing with a Client

				
					const ws = new WebSocket('ws://localhost:3000');

ws.onopen = () => ws.send('Hello Server!');
ws.onmessage = (event) => console.log(`Server: ${event.data}`);

				
			

Setting Up Server-Sent Events (SSE) in Express.js

SSE Server with Express.js

				
					const express = require('express');
const app = express();
const PORT = 3000;

// SSE Endpoint
app.get('/events', (req, res) => {
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');

  // Send initial event
  res.write(`data: Connected to SSE\n\n`);

  // Send periodic updates
  const interval = setInterval(() => {
    res.write(`data: ${new Date().toISOString()}\n\n`);
  }, 1000);

  // Cleanup on client disconnect
  req.on('close', () => {
    clearInterval(interval);
    res.end();
  });
});

// HTTP Server
app.get('/', (req, res) => {
  res.send('SSE with Express.js');
});

app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});

				
			

Explanation

  1. Headers: Set required headers for SSE.
  2. Event Data: Use res.write() to send data.
  3. Cleanup: Handle client disconnections.

Testing with a Client

				
					const eventSource = new EventSource('http://localhost:3000/events');

eventSource.onmessage = (event) => {
  console.log('New message:', event.data);
};

				
			

Comparing WebSocket and SSE

FeatureWebSocketSSE
CommunicationBi-directionalServer to Client
ComplexityHigherLower
Browser SupportNeeds polyfills for old browsersWidely supported
Connection CountOptimized for fewer clientsOptimized for many clients

Advanced Topics

Broadcasting in WebSocket

Broadcast messages to all clients:

				
					wss.on('connection', (ws) => {
  ws.on('message', (message) => {
    wss.clients.forEach((client) => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(message);
      }
    });
  });
});

				
			

Custom Event Names in SSE

Send named events:

				
					res.write(`event: customEvent\n`);
res.write(`data: Custom event data\n\n`);

				
			

Testing Real-Time Communication

Using WebSocket Clients

Tools like Postman and browser-based WebSocket clients can help test WebSocket connections.

Debugging SSE

Browser developer tools (Network tab) show the stream of events.

WebSocket and Server-Sent Events (SSE) are powerful tools for implementing real-time features in web applications using Express.js. Choose the protocol based on your application’s requirements, and implement robust real-time systems to deliver a dynamic user experience. The examples and strategies provided here should equip you to handle real-time communication challenges effectively. Happy coding !❤️

Table of Contents