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.