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:
- What Server-Sent Events are.
- How to set up SSE.
- How to implement an SSE server.
- How to use SSE in HTML5.
- 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:
- A server that sends data using a specific MIME type (text/event-stream).
- 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
- Fallback Mechanism:
- Use polling for browsers that do not support SSE (e.g., Internet Explorer).
- Limit Connections:
- Handle multiple connections carefully to avoid overwhelming the server.
- 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:
- How Server-Sent Events work.
- How to create an SSE server with Node.js.
- How to use the EventSource API in HTML5.
- 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.
