Skip to content
Learni
View all tutorials
Développement Web

Comment implémenter Server-Sent Events en 2026

Introduction

Server-Sent Events (SSE) est un standard web natif pour des communications unidirectionnelles du serveur vers le client en temps réel. Contrairement aux WebSockets (bidirectionnels), SSE est plus simple à implémenter : pas de gestion de trames complexes, reconnexion automatique, et support natif dans tous les navigateurs modernes.

Pourquoi l'utiliser en 2026 ? Pour des notifications live (nouveaux messages, alertes), mises à jour de dashboards (stats en temps réel), ou suivi de tâches longues sans recharger la page. C'est léger (texte brut via HTTP), scalable (connexions persistantes gérées par le navigateur), et évite le polling coûteux en ressources.

Ce tutoriel beginner vous guide pas à pas : du serveur Node.js basique à un client robuste avec reconnexion. À la fin, vous aurez un exemple fonctionnel copié-collable pour des événements personnalisés et données JSON. Temps estimé : 15 minutes.

Prérequis

  • Node.js 20+ installé
  • Connaissances basiques en JavaScript (variables, fonctions, async)
  • Un éditeur de code (VS Code recommandé)
  • Navigateur moderne (Chrome, Firefox)

Initialiser le projet et installer les dépendances

terminal
mkdir sse-tutorial
cd sse-tutorial
npm init -y
npm install express cors

Ce script crée un dossier projet, initialise package.json et installe Express pour le serveur HTTP, ainsi que CORS pour autoriser les requêtes cross-origin depuis le client. Lancez-le dans votre terminal pour un setup prêt en 30 secondes.

Comprendre les bases de SSE

SSE utilise un flux text/event-stream sur une connexion HTTP persistante. Le serveur envoie des messages au format data: message\n\n. Le client, via EventSource, écoute et parse automatiquement. Avantage : reconnexion auto après 3s si déconnexion.

Créer le serveur SSE basique

server.js
const express = require('express');
const cors = require('cors');
const app = express();

app.use(cors());

app.get('/events', (req, res) => {
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive',
    'Access-Control-Allow-Origin': '*'
  });

  let counter = 0;
  const interval = setInterval(() => {
    counter++;
    res.write(`data: Compteur: ${counter}\n\n`);
  }, 1000);

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

app.listen(3000, () => {
  console.log('Serveur SSE sur http://localhost:3000');
});

Ce serveur expose /events comme endpoint SSE. Il envoie un compteur incrémenté toutes les secondes. Les headers obligatoires activent le flux persistant ; req.on('close') nettoie l'intervalle pour éviter les fuites mémoire. Lancez avec node server.js.

Créer le client HTML simple

index.html
<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8">
  <title>SSE Client</title>
</head>
<body>
  <h1>Server-Sent Events Demo</h1>
  <div id="messages"></div>

  <script>
    const eventSource = new EventSource('http://localhost:3000/events');
    const messagesDiv = document.getElementById('messages');

    eventSource.onmessage = (event) => {
      const newMessage = document.createElement('p');
      newMessage.textContent = event.data;
      messagesDiv.appendChild(newMessage);
    };

    eventSource.onerror = (error) => {
      console.error('Erreur SSE:', error);
    };
  </script>
</body>
</html>

Ce fichier HTML autonome connecte à /events via EventSource. onmessage affiche chaque data reçue. onerror log les erreurs (reconnexion auto gérée par le navigateur). Ouvrez-le dans un navigateur pour voir le compteur live.

Tester la démo basique

  1. Lancez node server.js.
  2. Ouvrez index.html dans votre navigateur.
  3. Observez les messages arriver toutes les secondes. Fermez/réouvrez l'onglet : reconnexion auto !
Analogie : comme un flux radio unidirectionnel où le serveur DJ parle sans interruption.

Ajouter des événements personnalisés

server.js
const express = require('express');
const cors = require('cors');
const app = express();

app.use(cors());

app.get('/events', (req, res) => {
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive',
    'Access-Control-Allow-Origin': '*'
  });

  let counter = 0;
  const interval = setInterval(() => {
    counter++;
    if (counter % 5 === 0) {
      res.write(`event: alerte\ndata: Alerte niveau ${counter}!\n\n`);
    } else {
      res.write(`data: Compteur normal: ${counter}\n\n`);
    }
  }, 1000);

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

app.listen(3000, () => {
  console.log('Serveur SSE sur http://localhost:3000');
});

Amélioration : utilise event: nom pour typer les messages (ex: 'alerte'). Tous les 5 ticks, un événement spécial est envoyé. Cela permet de filtrer côté client. Remplacez l'ancien server.js et relancez.

Client avancé avec gestion d'événements et JSON

index.html
<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8">
  <title>SSE Client Avancé</title>
</head>
<body>
  <h1>SSE avec Événements Personnalisés</h1>
  <div id="normal"></div>
  <div id="alertes"></div>

  <script>
    const eventSource = new EventSource('http://localhost:3000/events');
    const normalDiv = document.getElementById('normal');
    const alertesDiv = document.getElementById('alertes');

    eventSource.addEventListener('alerte', (event) => {
      const data = JSON.parse(event.data);
      const alertDiv = document.createElement('div');
      alertDiv.style.color = 'red';
      alertDiv.textContent = `ALERTE: ${data.message}`;
      alertesDiv.appendChild(alertDiv);
    });

    eventSource.onmessage = (event) => {
      const p = document.createElement('p');
      p.textContent = event.data;
      normalDiv.appendChild(p);
    };

    eventSource.onerror = () => {
      console.log('Reconnexion en cours...');
    };
  </script>
</body>
</html>

Client filtre les événements via addEventListener('alerte'). Parse JSON pour données structurées. onerror gère gracieusement les déconnexions. Remplacez index.html ; maintenant, alertes en rouge !

Serveur avec données JSON dynamiques

server.js
const express = require('express');
const cors = require('cors');
const app = express();

app.use(cors());

let usersOnline = 0;

app.get('/events', (req, res) => {
  res.writeHead(200, {
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive',
    'Access-Control-Allow-Origin': '*'
  });

  const interval = setInterval(() => {
    usersOnline += Math.floor(Math.random() * 3) - 1;
    if (usersOnline < 0) usersOnline = 0;

    const data = { users: usersOnline, timestamp: Date.now() };

    res.write(`data: ${JSON.stringify(data)}\n\n`);
  }, 2000);

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

app.listen(3000, () => {
  console.log('Serveur SSE JSON sur http://localhost:3000');
});

Maintenant, envoie des objets JSON simulés (utilisateurs en ligne). Idéal pour dashboards réels. Le client précédent les parse automatiquement. Cela illustre des données complexes sans changer le protocole SSE.

Bonnes pratiques

  • Toujours cleaner les intervalles/timers sur req.close pour éviter les leaks.
  • Limitez les reconnexions : new EventSource(url, { heartbeatTimeout: 30000 }).
  • Utilisez ID pour resume : id: ${timestamp}\n côté serveur, géré auto par client.
  • Bufférisez les petits messages pour réduire la latence réseau.
  • Scalez avec Redis pour shared state multi-instances.

Erreurs courantes à éviter

  • Oublier 'Connection: keep-alive' : la connexion ferme après un message.
  • Ne pas gérer CORS : erreurs cross-origin bloquent le client.
  • Envoyer sans \n\n final : messages non parsés par EventSource.
  • Ignorer les multiples clients : utilisez un broadcaster comme ioredis pour scaler.

Pour aller plus loin

Comment implémenter Server-Sent Events en 2026 (Tutoriel) | Learni