- Published on
Server Sent Events in Node.js: A Comprehensive Guide (with Polling, Long Polling, and Nodemon)
- Authors
- Name
- Anil Sharma
- @realAnilSharma
Introduction
In the world of real-time web applications, there are several techniques to achieve real-time communication between the server and the client. Server-Sent Events (SSE)
, Polling
, and Long Polling
are some of the most common approaches. While WebSockets often steal the spotlight, SSE provides a simple and efficient way to push updates from the server to the client over a single HTTP connection. In this blog, we’ll explore what Server-Sent Events are, how they compare to Polling and Long Polling, and how to implement SSE in Node.js. We’ll also use Nodemon to automatically restart our Node.js server during development.
What are Server-Sent Events (SSE)?
Server-Sent Events (SSE) is a standard that allows a server to send real-time updates to a client over a single, long-lived HTTP connection. Unlike WebSockets, which enable full-duplex communication (both client and server can send messages), SSE is unidirectional—only the server can send data to the client. This makes SSE ideal for scenarios where the server needs to push updates, such as live notifications, stock tickers, or real-time analytics.
SSE is built on top of HTTP, making it easy to implement and integrate with existing web applications. It uses the text/event-stream
content type and sends data in a specific format, which the client can parse and handle.
Polling and Long Polling
Before diving into SSE, let’s briefly discuss two other techniques for real-time communication: Polling
and Long Polling
.
Polling
Polling is a technique where the client repeatedly sends requests to the server at regular intervals to check for updates. While simple to implement, polling can be inefficient because it involves frequent HTTP requests, even when there are no updates. This can lead to unnecessary network traffic and server load.
Example of Polling
setInterval(() => {
fetch('/updates')
.then(response => response.json())
.then(data => console.log(data));
}, 5000); // Poll every 5 seconds
Long Polling
Long Polling is an improvement over regular polling. Instead of sending requests at fixed intervals, the client sends a request to the server and waits for a response. The server holds the request open until new data is available or a timeout occurs. Once the client receives a response, it immediately sends another request. This reduces the number of requests compared to regular polling but can still be resource-intensive.
Example of Long Polling
function longPoll() {
fetch('/updates')
.then(response => response.json())
.then(data => {
console.log(data);
longPoll(); // Send another request immediately
});
}
longPoll();
Comparison with SSE
Polling: Inefficient due to frequent requests. Long Polling: Better than polling but still involves repeated connections. SSE: Efficient and persistent, with the server pushing updates to the client over a single connection.
Implementing SSE in Node.js with Nodemon
Let’s dive into how to implement Server-Sent Events in a Node.js application. We’ll use Nodemon to automatically restart the server whenever we make changes to our code. This is especially useful during development.
Step 1: Set Up a Node.js Project
First, create a new Node.js project and install the necessary dependencies:
mkdir sse-example
cd sse-example
npm init -y
npm install express nodemon
Step 2: Create the Server
Create a file named server.js
and add the following code:
const express = require('express');
const app = express();
app.get('/events', (req, res) => {
// Set headers for SSE
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
res.setHeader('Access-Control-Allow-Origin', '*');
// Send a message every 2 seconds
const intervalId = setInterval(() => {
const data = JSON.stringify({ message: `Hello at ${new Date().toLocaleTimeString()}` });
res.write(`data: ${data}\n\n`); // SSE format
}, 2000);
// Clean up on client disconnect
req.on('close', () => {
clearInterval(intervalId);
res.end();
});
});
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
Step 3: Configure Nodemon
To use Nodemon, update the scripts
section in your package.json
file:
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js"
}
Now, you can start the server in development mode using:
npm run dev
Nodemon will automatically restart the server whenever you make changes to server.js
.
Step 4: Create the Client
Create an index.html
file to consume the SSE stream:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SSE Example</title>
</head>
<body>
<h1>Server-Sent Events Example</h1>
<div id="messages"></div>
<script>
const eventSource = new EventSource('http://localhost:3000/events');
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
const messageElement = document.createElement('p');
messageElement.textContent = data.message;
document.getElementById('messages').appendChild(messageElement);
};
eventSource.onerror = () => {
console.error('EventSource failed.');
eventSource.close();
};
</script>
</body>
</html>
Step 5: Run the Application
- Start the server in development mode:
npm run dev
. - Open the
index.html
file in your browser. - You should see real-time messages appearing every 2 seconds.
Use Cases for Server-Sent Events
SSE is particularly useful in scenarios where the server needs to push updates to the client without requiring bidirectional communication. Some common use cases include:
- Real-Time Notifications: Push notifications for new messages, alerts, or updates.
- Live Feeds: Display live updates such as news feeds, sports scores, or stock prices.
- Progress Updates: Show progress for long-running tasks like file uploads or data processing.
- Dashboards: Update dashboards with real-time metrics and analytics.
- Chat Applications: Send messages to clients in a one-way chat system.
UPros of Server-Sent Events
Simplicity: SSE is easy to implement and uses standard HTTP, making it compatible with existing infrastructure. Automatic Reconnection: The client automatically reconnects if the connection is lost. Efficient: SSE uses a single HTTP connection, reducing overhead compared to polling. Browser Support: SSE is supported in most modern browsers, including Chrome, Firefox, Safari, and Edge. No Need for Additional Libraries: Unlike WebSockets, SSE doesn’t require additional libraries or protocols.
Cons of Server-Sent Events
Unidirectional: SSE only allows the server to send data to the client. If bidirectional communication is needed, WebSockets are a better choice.
Limited Browser Support in Older Browsers: Older browsers like Internet Explorer do not support SSE.
Connection Limits: Browsers impose a limit on the number of simultaneous HTTP connections, which can be a bottleneck for applications with many clients.
No Binary Data: SSE is limited to text-based data, making it unsuitable for scenarios requiring binary data transfer
When to Use SSE vs. Polling vs. WebSockets
Use Polling for simple use cases where real-time updates are not critical, and you want a straightforward implementation.
Use Long Polling when you want to reduce the number of requests compared to regular polling but don’t need the efficiency of SSE.
Use SSE when you only need server-to-client communication and want a simple, lightweight solution.
Use WebSockets when you need full-duplex communication or have more complex real-time requirements.
Conclusion
Server-Sent Events are a powerful tool for building real-time web applications. They are simple to implement, efficient, and well-suited for scenarios where the server needs to push updates to the client. By using Nodemon, we can streamline the development process and automatically restart the server whenever changes are made.
If you’re building a real-time application in Node.js, consider giving SSE a try. It might just be the perfect solution for your needs!
Happy coding!