DEV Community

Cover image for Getting Started with Server-Sent Events (SSE) using Express.js and EventSource
CodingWith-Adam
CodingWith-Adam

Posted on

Getting Started with Server-Sent Events (SSE) using Express.js and EventSource

Server-Sent Events (SSE) is a technology that allows a server to push updates to the client over a single HTTP connection. It's a great way to handle real-time data in web applications, offering a simpler alternative to WebSockets for many use cases.

If you prefer watching a tutorial, you can watch the accompanying video here. The video provides a step-by-step guide and further explanations to help you understand SSE better. It goes into more details than the written tutorial below.

Understanding HTTP Requests and Responses

First, let's take a look at how a typical set of HTTP requests and responses work. In the diagram below, you can see that the client opens a connection for a resource such as an image, HTML file, or API call. The client then receives a response, and the connection closes. The client can then open another connection to make another request and receive a response, at which point the connection closes again.

HTTP Request Response Diagram

Understanding Server-Sent Events (SSE)

With Server-Sent Events (SSE), a client can open a connection with a request and keep that connection open to receive multiple responses from the server. Once the connection is open, the communication direction is one-way: from the server to the client. The client cannot make additional requests over the same connection.

The client initiates the connection with a request using an Accept header of text/event-stream. The server responds with a Content-Type of text/event-stream and typically uses Transfer-Encoding: chunked. This encoding allows the server to send multiple chunks of data without knowing the total size of the response beforehand.

In the diagram below, you can see how the SSE connection is established and how data flows from the server to the client:

Server Sent Events Diagram

Project Structure

We'll be organizing our project into two main folders: server for the backend and client for the frontend.

sse-example/
├── client/
│   ├── index.html
│   └── index.js
└── server/
    ├── index.js
    └── package.json
Enter fullscreen mode Exit fullscreen mode

Setting Up the Server

First, we'll create an Express.js server that can handle SSE connections. You'll need Node.js installed on your machine. Navigate to the server folder and initialize a new Node.js project:

mkdir server
cd server
npm init -y
Enter fullscreen mode Exit fullscreen mode

Install the necessary dependencies:

npm install express cors
npm install --save-dev nodemon
Enter fullscreen mode Exit fullscreen mode

To use ES6 imports, make sure your package.json includes "type": "module":

package.json

{
  "name": "sse-example",
  "version": "1.0.0",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "start": "nodemon index.js"
  },
  "dependencies": {
    "express": "^4.17.1",
    "cors": "^2.8.5"
  },
  "devDependencies": {
    "nodemon": "^2.0.7"
  }
}
Enter fullscreen mode Exit fullscreen mode

Next, create a file called index.js in the server folder and add the following code:

import express from 'express';
import cors from 'cors';

const app = express();
const port = 3000;

app.use(cors());

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

    const intervalId = setInterval(() => {
        res.write(`data: ${new Date().toLocaleTimeString()}\n\n`);
    }, 1000);

    req.on('close', () => {
        clearInterval(intervalId);
        res.end();
    });
});

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}`);
});
Enter fullscreen mode Exit fullscreen mode

In this code, we create an Express.js server that listens for GET requests on the /currentTime endpoint. The server sets the necessary headers for SSE and sends a timestamp to the client every second as a simple string. We also handle client disconnections by clearing the interval and ending the response.

Setting Up the Client

For the client side, we'll use a simple HTML file and JavaScript to handle the SSE stream. Create a client folder and create the following files index.html and index.js as per the file structure:

sse-example/
├── client/        <-- Here
│   ├── index.html <-- Here
│   └── index.js   <-- Here
└── server/
    ├── index.js
    └── package.json
Enter fullscreen mode Exit fullscreen mode

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script defer src="index.js"></script>
    <style>
      body {
        background-color: black;
        color: white;
      }
    </style>
  </head>
  <body>
    <h1 id="time">Time</h1>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

index.js

const eventSource = new EventSource('http://localhost:3000/currentTime');

eventSource.onmessage = function(event) {
    document.getElementById('time').textContent = `${event.data}`;
};

eventSource.onerror = function() {
    console.log("EventSource failed.");
};
Enter fullscreen mode Exit fullscreen mode

In this HTML and JavaScript setup, we create a connection to the server using EventSource and update the time displayed in the DOM as new messages are received. We also handle any errors that might occur with the EventSource connection.

Running the Example

To run the example, start the Express.js server by executing:

cd server
npm start
Enter fullscreen mode Exit fullscreen mode

Then, open index.html using VS Code Live Server extension. Install VS Code Live server if you have not already by going to the extensions tab and finding live server and clicking install. Once installed right click the index.Html file and click Open With Live Server. Your default browser will open and you should see see the time being updated every second.

Conclusion

Server-Sent Events provide an efficient way to handle real-time updates in web applications. With just a few lines of code, you can set up an SSE server and client to stream data seamlessly. Give it a try in your next project and enjoy the simplicity and power of SSE!

Feel free to reach out with any questions or feedback in the comments below. Happy coding!

Top comments (0)