Node.js - server-sent events example using Express.js
In this article, we would like to show how to use server-sent events with Express.js under Node.js.
In the example project we used HTTP/2 protocol for better performance (spdy
package).
Warning from MDN:
When not used over HTTP/2, SSE suffers from a limitation to the maximum number of open connections, which can be specially painful when opening various tabs as the limit is per browser and set to a very low number (6). The issue has been marked as "Won't fix" in Chrome and Firefox. This limit is per browser + domain, so that means that you can open 6 SSE connections across all of the tabs to
www.example1.com
and another 6 SSE connections towww.example2.com.
(from Stackoverflow). When using HTTP/2, the maximum number of simultaneous HTTP streams is negotiated between the server and the client (defaults to 100).Source: https://developer.mozilla.org/en-US/docs/Web/API/EventSource

To generate cert.pem
and key.pem
files use the following command:
xxxxxxxxxx
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj '/CN=localhost'
Hint: to know how to generate certificate files under Windows read this article.
package.json
file:
xxxxxxxxxx
{
"name": "server-sent-events",
"version": "1.0.0",
"description": "",
"scripts": {
"start": "node server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.18.2",
"spdy": "^4.0.2"
}
}
index.html
file:
xxxxxxxxxx
<html>
<body>
<script>
const source = new EventSource('/events'); // OR: https://localhost:8443/events
source.onopen = (e) => console.log('Event source stream open!');
source.onerror = (e) => console.error('Event source stream error!');
// Handling specific events:
source.addEventListener('my-message', (e) => console.log('Message: ' + e.data));
// Add here more source.addEventListener(...) calls for different events ...
</script>
</body>
</html>
Note: event source can be closed by
source.close()
method call.
server.js
file:
xxxxxxxxxx
const fs = require('fs');
const path = require('path');
const spdy = require('spdy'); // npm install spdy
const express = require('express'); // npm install express
// Configuration:
const port = 8443;
const credentials = {
key: fs.readFileSync(path.join(__dirname, 'key.pem'), 'utf8'),
cert: fs.readFileSync(path.join(__dirname, 'cert.pem'), 'utf8')
};
// Helpers:
const createEventStream = (response) => {
let counter = 0;
response.writeHead(200, {
'Connection': 'keep-alive',
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache'
});
response.flushHeaders();
return (event, data) => {
response.write(`id: ${++counter}\n`);
response.write(`event: ${event}\n`);
response.write(`data: ${data}\n`);
response.write(`\n`);
};
};
// Application:
const app = express();
app.get('/', (request, response) => {
response.sendFile(path.join(__dirname, 'index.html'));
});
app.get('/events', (request, response) => {
response.once('close', () => {
console.log('Event source stream closed!');
});
const sendEventMessage = createEventStream(response);
setInterval(() => sendEventMessage('my-message', 'Some text message here ...'), 1000); // we sent message once per second
});
const server = spdy.createServer(credentials, app);
server.listen(port, () => console.log(`Server started on https://localhost:${port}`));
To all dependencies use the following command:
xxxxxxxxxx
npm install
To run server use the following command:
xxxxxxxxxx
node server.js
Then, to see the final effect, open the link in the web browser: https://localhost:8443
Example preview:
