Back

Echtzeit-UX mit der htmx-SSE-Erweiterung

Echtzeit-UX mit der htmx-SSE-Erweiterung

Die meisten Webanwendungen benötigen irgendwann Live-Updates – ein Benachrichtigungs-Badge, eine Fortschrittsanzeige, ein Dashboard, das sich ohne Polling aktualisiert. Die übliche Antwort sind WebSockets oder ein vollständiges SPA-Framework. Aber wenn Sie bereits htmx verwenden, gibt es einen einfacheren Weg: die htmx-SSE-Erweiterung, die Server-Sent Events direkt in Ihr HTML einbindet – nahezu ohne JavaScript.

Wichtigste Erkenntnisse

  • Server-Sent Events (SSE) bieten unidirektionales Streaming vom Server zum Client über Standard-HTTP – ideal für Benachrichtigungen, Dashboards und Live-Feeds.
  • Die htmx-SSE-Erweiterung ist ein separates Paket (htmx-ext-sse), das SSE-Streams mithilfe deklarativer Attribute mit Ihrem HTML verbindet, ohne dass benutzerdefiniertes JavaScript erforderlich ist.
  • Drei zentrale Attribute – sse-connect, sse-swap und hx-trigger="sse:<event>" – decken die meisten Echtzeit-UX-Muster ab.
  • SSE ist einfacher zu deployen als WebSockets und eliminiert die verschwendeten Requests beim Polling, unterstützt allerdings nur Server-zu-Client-Kommunikation.

Was Server-Sent Events eigentlich sind

Server-Sent Events (SSE) ist ein browsernatives Protokoll für unidirektionales Streaming vom Server zum Client über eine Standard-HTTP-Verbindung. Der Server hält die Verbindung offen und sendet Text-Events, wann immer er etwas mitzuteilen hat. Der Browser empfängt sie über die EventSource-API.

Das Wire-Format ist reiner Text:

event: priceUpdate
data: <li>BTC — $62,400</li>

Jedes Event hat einen optionalen Namen und eine data-Payload. Mehrere data:-Zeilen werden konkateniert. Events werden durch eine Leerzeile getrennt.

Da SSE über HTTP läuft, funktioniert es durch Proxys und Firewalls hindurch ohne spezielle Konfiguration. Es unterstützt automatische Wiederverbindung nativ. Der Kompromiss liegt in der Richtung: Sobald die Verbindung offen ist, kann der Client keine Nachrichten zurücksenden. Für Benachrichtigungen, Dashboards, Job-Fortschritt und Live-Feeds ist das völlig ausreichend. Für Chat oder kollaboratives Editieren würden Sie stattdessen WebSockets benötigen.

Installation der htmx-SSE-Erweiterung

SSE-Unterstützung ist nicht in htmx Core integriert. Sie befindet sich im separaten Paket htmx-ext-sse. Laden Sie beide Skripte und aktivieren Sie die Erweiterung auf einem Container-Element:

<head>
  <script  src="https://cdn.jsdelivr.net/npm/htmx.org@latest/dist/htmx.min.js"></script>  
  <script  src="https://cdn.jsdelivr.net/npm/htmx-ext-sse@latest"></script>
</head>
<body hx-ext="sse">

Für npm-basierte Builds installieren Sie mit npm install htmx-ext-sse und importieren Sie sowohl htmx.org als auch htmx-ext-sse in Ihrer Entry-Datei.

Hinweis: Das alte hx-sse-Attribut aus früheren htmx-Versionen ist veraltet. Verwenden Sie stattdessen hx-ext="sse" mit der dedizierten Erweiterung.

Zentrale Attribute für htmx-Streaming-Updates

Drei Attribute decken die meisten Echtzeit-UX-Muster ab:

AttributZweck
sse-connect="<url>"Öffnet die EventSource-Verbindung
sse-swap="<event-name>"Tauscht eingehendes HTML in das Element ein
hx-trigger="sse:<event-name>"Löst einen htmx-Request aus, wenn das Event eintrifft

Ein Live-Feed, der seinen eigenen Inhalt bei jedem Push ersetzt:

<div hx-ext="sse" sse-connect="/feed" sse-swap="message">
  Lädt…
</div>

Der Server sendet ein Event mit data: <p>Neues Element</p> gefolgt von einer Leerzeile, und htmx ersetzt den Inhalt des div – kein JavaScript erforderlich.

Umgang mit mehreren Events und Auslösen von Requests

Ein sse-connect kann mehrere untergeordnete Elemente versorgen, die jeweils auf einen anderen Event-Namen hören:

<div hx-ext="sse" sse-connect="/stream">
  <div sse-swap="statsUpdate"></div>
  <div sse-swap="alertBanner"></div>
</div>

Sie können SSE-Events auch verwenden, um Folge-HTTP-Requests auszulösen, anstatt Inhalte direkt auszutauschen. Dies ist nützlich, wenn das Event signalisiert, dass neue Daten verfügbar sind, Sie aber möchten, dass htmx das vollständig gerenderte Fragment abruft:

<div hx-ext="sse" sse-connect="/events">
  <div hx-get="/notifications" hx-trigger="sse:newNotification">
    <!-- wird bei jedem SSE-Event aktualisiert -->
  </div>
</div>

Um einen Stream ordnungsgemäß zu schließen, wenn der Server die Fertigstellung signalisiert, fügen Sie sse-close="done" hinzu – die Verbindung wird geschlossen, wenn ein Event namens done eintrifft.

Wann SSE Polling oder WebSockets übertrifft

  • vs. Polling: SSE eliminiert verschwendete Requests. Der Server pusht nur, wenn sich etwas ändert.
  • vs. WebSockets: SSE ist einfacher zu deployen, funktioniert über HTTP/1.1 und HTTP/2 und benötigt keine spezielle Server-Infrastruktur. Verwenden Sie WebSockets nur, wenn Sie bidirektionale Kommunikation benötigen.

Ein praktischer Hinweis: HTTP/1.1-Browser begrenzen Verbindungen pro Domain auf sechs. Wenn Benutzer mehrere Tabs öffnen, konkurrieren SSE-Verbindungen um dieses Limit. Die Bereitstellung über HTTP/2 vermeidet diese Einschränkung weitgehend, indem mehrere Streams über eine einzige Verbindung gemultiplext werden.

Fazit

Die htmx-SSE-Erweiterung ermöglicht es Ihnen, echte HTML-over-the-Wire-Echtzeit-UI hinzuzufügen – Live-Dashboards, Fortschrittsindikatoren, Benachrichtigungs-Streams – mit ein paar HTML-Attributen und einem Server-Endpoint, der weiß, wie man eine Verbindung offen hält. Keine State-Management-Bibliothek, kein clientseitiges Routing, keine Build-Pipeline erforderlich. Wenn Ihr Server Text streamen kann, kann Ihre UI live sein.

FAQs

Nein. Server-Sent Events sind strikt unidirektional, vom Server zum Client. Wenn Sie Daten zurücksenden müssen, kombinieren Sie Ihren SSE-Stream mit Standard-htmx-Requests unter Verwendung von hx-post oder hx-put. Für vollständig bidirektionale Kommunikation, wie z. B. Echtzeit-Chat, sind WebSockets die bessere Wahl.

Die in den Browser integrierte EventSource-API versucht nach einer kurzen Verzögerung automatisch, die Verbindung wiederherzustellen. Der Server kann das Retry-Intervall steuern, indem er ein retry-Feld im Event-Stream einschließt. Die htmx-SSE-Erweiterung übernimmt dieses Wiederverbindungsverhalten ohne zusätzliche Konfiguration Ihrerseits.

Ja, und HTTP/2 wird sogar empfohlen. Unter HTTP/1.1 begrenzen Browser gleichzeitige Verbindungen pro Domain auf etwa sechs, sodass mehrere Tabs mit offenen SSE-Streams dieses Limit erschöpfen können. HTTP/2 multiplext Streams über eine einzige Verbindung und hebt die Obergrenze effektiv auf.

Senden Sie ein benanntes Event, das mit dem Wert des sse-close-Attributs auf Ihrem Container-Element übereinstimmt. Wenn Sie beispielsweise sse-close auf done setzen, führt das Senden eines Events mit dem Namen done dazu, dass die Erweiterung die EventSource-Verbindung auf der Client-Seite sauber schließt.

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay