Home » HTML5 Server-Sent Events (SSE) Tutorial

HTML5 Server-Sent Events (SSE) Tutorial

by shedders

Server-Sent Events (SSE) is a technology in HTML5 that allows servers to push updates to the client over a single, long-lived HTTP connection. Unlike WebSockets, which provide full-duplex communication, SSE is one-way: data flows from the server to the client.

In this tutorial, you’ll learn:

  1. What Server-Sent Events are.
  2. How to set up SSE.
  3. How to implement an SSE server.
  4. How to use SSE in HTML5.
  5. Practical examples of SSE.

1. What are Server-Sent Events?

SSE is designed for real-time updates like:

  • Notifications
  • Live sports scores
  • Stock price updates
  • Chat applications (receive-only messages)

SSE uses the EventSource API on the client side to receive data from the server.

Advantages of SSE:

  • Built-in browser support.
  • Uses HTTP/1.1 for easy integration with existing servers.
  • Automatically reconnects if the connection drops.

2. Setting Up Server-Sent Events

SSE requires:

  1. A server that sends data using a specific MIME type (text/event-stream).
  2. A client that listens for events using the EventSource API.

3. Implementing an SSE Server

Example 1: Simple Node.js Server

// Install Node.js if not already installed

const http = require("http");

const server = http.createServer((req, res) => {
    if (req.url === "/events") {
        // Set the headers for SSE
        res.writeHead(200, {
            "Content-Type": "text/event-stream",
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
        });

        // Send an initial message
        res.write("data: Hello, this is a Server-Sent Event!\n\n");

        // Send messages every 3 seconds
        let count = 0;
        const interval = setInterval(() => {
            count++;
            res.write(`data: Message ${count} at ${new Date().toLocaleTimeString()}\n\n`);
        }, 3000);

        // Cleanup when the connection is closed
        req.on("close", () => {
            clearInterval(interval);
            res.end();
        });
    } else {
        res.writeHead(404);
        res.end("Not Found");
    }
});

server.listen(8080, () => {
    console.log("SSE server running at http://localhost:8080");
});

Explanation:

  • Content-Type: text/event-stream: Specifies the MIME type for SSE.
  • data: <message>: Sends a message.
  • Double newline (\n\n): Indicates the end of a message.

4. Using SSE in HTML5

The client-side implementation uses the EventSource API to receive updates.

Example 2: Basic SSE Client

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Server-Sent Events</title>
</head>
<body>
    <h1>Server-Sent Events Example</h1>
    <div id="messages">Waiting for messages...</div>

    <script>
        // Create a new EventSource instance
        const eventSource = new EventSource("http://localhost:8080/events");

        // Listen for messages from the server
        eventSource.onmessage = (event) => {
            const messages = document.getElementById("messages");
            const newMessage = document.createElement("p");
            newMessage.textContent = event.data;
            messages.appendChild(newMessage);
        };

        // Handle errors
        eventSource.onerror = () => {
            console.error("EventSource connection error.");
        };
    </script>
</body>
</html>

Explanation:

  • new EventSource(url): Connects to the server.
  • onmessage: Handles messages received from the server.
  • event.data: Contains the server-sent message.

5. Sending Custom Events

SSE supports named events for better control.

Example 3: Custom Event Names on the Server

Modify the Node.js server to send named events:

res.write("event: customEvent\n");
res.write("data: This is a custom event!\n\n");

Example 4: Listening to Custom Events on the Client

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Custom SSE Events</title>
</head>
<body>
    <h1>Custom Server-Sent Events</h1>
    <div id="messages">Waiting for messages...</div>

    <script>
        const eventSource = new EventSource("http://localhost:8080/events");

        // Listen for custom events
        eventSource.addEventListener("customEvent", (event) => {
            const messages = document.getElementById("messages");
            const newMessage = document.createElement("p");
            newMessage.textContent = `Custom Event: ${event.data}`;
            messages.appendChild(newMessage);
        });

        eventSource.onerror = () => {
            console.error("EventSource connection error.");
        };
    </script>
</body>
</html>

Explanation:

  • event: <event-name>: Specifies the event name.
  • addEventListener: Listens for specific event names.

6. Reconnection Handling

The browser automatically reconnects if the connection drops. You can control this using the retry field.

Example 5: Setting Reconnection Interval

Modify the Node.js server:

res.write("retry: 5000\n"); // Retry every 5 seconds
res.write("data: Reconnection test\n\n");

Explanation:

  • retry: <milliseconds>: Sets the reconnection interval.

7. Practical Application: Live Notifications

Example 6: Live Notification System

Server (Node.js):

const http = require("http");

let clients = [];

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",
        });

        clients.push(res);

        req.on("close", () => {
            clients = clients.filter(client => client !== res);
        });
    } else if (req.url === "/notify") {
        clients.forEach((client) => {
            client.write(`data: New notification at ${new Date().toLocaleTimeString()}\n\n`);
        });
        res.writeHead(200);
        res.end("Notification sent!");
    } else {
        res.writeHead(404);
        res.end("Not Found");
    }
});

server.listen(8080, () => {
    console.log("SSE notification server running at http://localhost:8080");
});

Client:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Live Notifications</title>
</head>
<body>
    <h1>Live Notifications</h1>
    <div id="notifications">No notifications yet...</div>

    <script>
        const eventSource = new EventSource("http://localhost:8080/events");

        eventSource.onmessage = (event) => {
            const notifications = document.getElementById("notifications");
            const newNotification = document.createElement("p");
            newNotification.textContent = event.data;
            notifications.appendChild(newNotification);
        };

        eventSource.onerror = () => {
            console.error("EventSource connection error.");
        };
    </script>
</body>
</html>

8. Best Practices

  1. Fallback Mechanism:
    • Use polling for browsers that do not support SSE (e.g., Internet Explorer).
  2. Limit Connections:
    • Handle multiple connections carefully to avoid overwhelming the server.
  3. Security:
    • Use HTTPS for secure connections.
    • Validate incoming data to prevent injection attacks.

9. Browser Support

Browser Support for SSE
Google Chrome Yes
Firefox Yes
Safari Yes
Microsoft Edge Yes (Chromium-based)
Internet Explorer No

10. Conclusion

In this tutorial, you learned:

  1. How Server-Sent Events work.
  2. How to create an SSE server with Node.js.
  3. How to use the EventSource API in HTML5.
  4. Practical examples like live notifications and custom events.

SSE is ideal for real-time, one-way data streaming. It’s simple to implement and works seamlessly for live updates.

You may also like