Get Real-Time Updates With Server-Sent Events

There are many ways to implement real-time updates to a web browser; Server-Sent Events (SSE) is a straightforward and simple way to push updates to the browser. SSE is a standardized technology for enabling server-to-client communication over HTTP. This technology allows servers to send data to clients in real-time without needing them to continually poll for updates or use WebSockets (more on WebSockets later).

I recently discovered SSE while learning how ChatGPT incrementally pushes responses to the browser; SSE is that tool. Let’s look at SSE and how we can use SSE to stream server events to the client.

The Basics

SSE uses the HTTP protocols you already know. It uses a single, long-lasting connection to send data after the initial request. First, a connection is established to the server using JavaScript’s EventSource API. When the server receives the request, it responds with an HTTP response, but returns the Content-Type header as text/event-stream. This indicates that this is a stream of events, not a one-off data transfer. And, the connection between the client and the server remains open after the response is sent, allowing the server to push updates to the browser.

If the connection gets lost, the client will automatically attempt to reconnect after a certain timeout, ensuring a persistent connection. The server sends a message over the established connection when new data is pushed. This is a simple text message, each body line prefixed with data:

An Example Built With Express

This example streams a list of company names to the browser, sending a new company name every second.

The backend code uses Express to open an event-stream connection when a get request is sent to the \events endpoint:


import express from 'express';
import cors from 'cors';
import { company_name } from 'casual';

const app = express();

app.use(cors());

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

  let eventId = 0;
  setInterval(() => {
    eventId += 1;
    res.write(`id: ${eventId}\ndata: ${company_name}\n\n`);
  }, 1000);
});

export default app;

The frontend page uses the EventSource API to update the DOM when new events are received.


<!DOCTYPE html>
<html lang="en">
<head>
    <title>Streamed Events Display</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: #f4f4f4;
            margin: 0;
            padding: 0;
        }

        h1 {
            background-color: #333;
            color: #fff;
            padding: 10px 0;
            text-align: center;
            margin: 0;
        }

        #events {
            white-space: pre-wrap;
            font-family: monospace;
            border: 1px solid #ddd;
            padding: 20px;
            margin: 20px auto;
            background-color: #fff;
            width: 80%;
            box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.1);
        }
    </style>
</head>
<body>
    <h1>Streamed Events:</h1>
    <div id="events"></div>

    <script>
        const eventSource = new EventSource("http://localhost:3001/events");
        const eventsDiv = document.getElementById("events");

        eventSource.onmessage = function(e) {
            eventsDiv.textContent += e.data + "\n";
        };

        eventSource.onerror = function() {
            eventsDiv.textContent += "Error occurred while receiving events.";
        };
    </script>
</body>
</html>

WebSockets vs. Server-Sent Events

Websockets are a popular way to enable two-way communication between the server and client. Let’s compare SSE to Websockets.

Up first, SSE:

  • ✅ API is simple to use.
  • ✅ Automatic Reconnection.
  • Good browser support, with the ability to use polyfill to fill in the gaps.
  • ❌ Unidirectional server-client communication can be limiting.
  • ❌ Limited to transferring text data encoded using UTF-8.

WebSockets:

  • ✅ Bidirectional communication.
  • ✅ Messages can be sent in UTF-8 or binary.
  • Good browser support.
  • ❌ More complex to implement.
  • ❌ No automatic reconnection.

 

The next time you want to add real-time updates to your application, consider using Server-Sent Events. It’s a simple way to stream updates to the client without implementing WebSockets.

Conversation

Join the conversation

Your email address will not be published. Required fields are marked *