Menu

📡 ssexi.js: server-sent events

Overview

ssexi.js is a small companion to fixi that adds Server-Sent Events support: a long-lived HTTP stream where the server pushes HTML to the browser as things happen.

ssexi adds no new attributes of its own. It hooks into fixi’s request lifecycle and treats any response with Content-Type: text/event-stream as a live stream, swapping each incoming message into fx-target using fx-swap.

That means every fixi attribute you already use applies; the only thing that changes is the server’s content type.

Events

ssexi dispatches a set of events on the target element during the stream lifecycle. All events bubble and are cancelable.

event when
fx:sse:open the SSE stream has been detected and is about to start. preventDefault() aborts processing.
fx:sse:message fired for every SSE message before swapping. preventDefault() stops the stream.
fx:sse:swapped after a message’s data has been swapped in. Useful for auto-scroll, syntax highlighting, etc.
fx:sse:{eventName} fired for messages with a (non-JSON) event: field. These messages are not swapped.
fx:sse:close the stream has ended normally.
fx:sse:error an error occurred during streaming.

The event.detail object includes cfg (the fixi config) along with response, message, or error depending on the event.

Examples

Below are some ssexi examples, building on fixi.

Live Feed

A div that subscribes to a /feed stream on init and appends each incoming message to its inner contents:

<div fx-trigger="fx:init" fx-action="/feed" fx-swap="beforeend"></div>

The server responds with text/event-stream and emits one data: <p>...</p> per push. fx-swap="beforeend" appends each fragment as it arrives.

Routing One Stream To Multiple Targets

By default one stream feeds one target. If a single stream needs to drive several parts of the page, the server can name an event with a JSON object instead of a plain word:

event: {"target":"#sidebar","swap":"innerHTML"}
data: <ul>...</ul>

event: {"target":"#feed","swap":"beforeend"}
data: <article>...</article>

ssexi parses the event name as JSON, resolves target via document.querySelector, and swaps using the named strategy. Any of target, swap, and transition can be omitted; they fall back to the values on cfg.

Plain (non-JSON) event names fire as ordinary fx:sse:{name} events on the subscribing element, so moxi handlers like on-fx:sse:done can react to them.

Auto-Scrolling Log

Streaming a log to a fixed-height div with a moxi handler that pins the scroll to the bottom after each swap:

<div id="log"
     fx-trigger="fx:init"
     fx-action="/logs/stream"
     fx-swap="beforeend"
     on-fx:sse:swapped="this.scrollTop = this.scrollHeight"></div>

fx:sse:swapped fires after each message has been inserted into the DOM, which is exactly when reading and setting scrollHeight gives the right value.

Reference

For the full event reference, the cfg.sse object, reconnection flags, and server-side examples in Python and Node, see the ssexi README on GitHub.

Next up is rexi.js, which makes fetch() more pleasant to work with.