htmx サーバー送信イベント (SSE) 拡張機能

サーバー送信イベント拡張機能は、HTML から直接 EventSource に接続します。Web サーバーへの接続を管理し、サーバーイベントをリッスンし、そのコンテンツをリアルタイムで htmx ウェブページに置き換えます。

SSE は、既存の HTTP 接続を介して動作する軽量な WebSockets の代替手段であるため、プロキシサーバーやファイアウォールを介して簡単に使用できます。SSE は一方向サービスであるため、接続が確立された後、SSE サーバーにメッセージを送信することはできません。双方向通信が必要な場合は、代わりに WebSockets を検討してください。

この拡張機能は、以前のバージョンの htmx に組み込まれていた実験的な hx-sse 属性に取って代わります。以前のバージョンからの移行に関するヘルプについては、このページの下部にある移行ガイドを参照してください。

以下の属性を使用して、SSE 接続の動作を構成します。

インストール


<script src="https://unpkg.com/htmx-ext-sse@2.2.2/sse.js"></script>

使用方法


<div hx-ext="sse" sse-connect="/chatroom" sse-swap="message">
    Contents of this box will be updated in real time
    with every SSE message received from the chatroom.
</div>

SSE サーバーへの接続

SSE サーバーに接続するには、hx-ext="sse" 属性を使用してその HTML 要素に拡張機能をインストールし、sse-connect="<url>" を要素に追加して接続します。

サーバーアプリケーションを設計する際には、SSE は HTTP リクエストとまったく同じように動作することに注意してください。接続を確立した後、サーバーにメッセージを送信することはできませんが、リクエストとともにパラメーターをサーバーに送信できます。そのため、https://my-server/chat-updates でサーバーへの SSE 接続を行う代わりに、https://my-server/chat-updates?friends=true&format=detailed に接続することもできます。これにより、サーバーはクライアントのニーズに合わせてレスポンスをカスタマイズできます。

名前付きイベントの受信

SSE メッセージは、イベント名とデータパケットで構成されます。メッセージには他のメタデータは許可されません。例を以下に示します。

event: EventName
data: <div>Content to swap into your HTML page.</div>

sse-swap 属性を使用してこのイベントをリッスンし、そのコンテンツをウェブページに置き換えます。


<div hx-ext="sse" sse-connect="/event-source" sse-swap="EventName"></div>

サーバーのメッセージのEventNameという名前は、sse-swap属性の値と一致する必要があることに注意してください。サーバーは必要な数の異なるイベント名を使用できますが、注意が必要です。ブラウザは、明示的に名前が付けられたイベントのみをリッスンできます。したがって、サーバーがChatroomUpdateという名前のイベントを送信しても、ブラウザがChatUpdateという名前のイベントのみをリッスンしている場合、余分なイベントは破棄されます。

名前のないイベントの受信

SSE メッセージは、イベント名なしで送信することもできます。この場合、ブラウザはその代わりにデフォルト名messageを使用します。上記で指定された同じルールが適用されます。サーバーが名前のないメッセージを送信する場合は、sse-swap="message"を含めることでリッスンする必要があります。キャッチオール名を使用するオプションはありません。これは次のようになります。

data: <div>Content to swap into your HTML page.</div>

<div hx-ext="sse" sse-connect="/event-source" sse-swap="message"></div>

複数のイベントの受信

単一の EventSource から複数のイベント(名前付きまたは名前なし)をリッスンすることもできます。リスナーは、1)hx-extおよびsse-connect属性を含む要素と同じ要素、または2)hx-extおよびsse-connect属性を含む要素の子要素のいずれかでなければなりません。


Multiple events in the same element
<div hx-ext="sse" sse-connect="/server-url" sse-swap="event1,event2"></div>

Multiple events in different elements (from the same source).
<div hx-ext="sse" sse-connect="/server-url">
    <div sse-swap="event1"></div>
    <div sse-swap="event2"></div>
</div>

サーバーコールバックのトリガー

サーバー送信イベントの接続が確立されると、子要素は特別なhx-trigger構文sse:<event_name>を使用してこれらのイベントをリッスンできます。これは、hx-getなどとの組み合わせで、要素にリクエストをトリガーさせます。

例を以下に示します。


<div hx-ext="sse" sse-connect="/event_stream">
    <div hx-get="/chatroom" hx-trigger="sse:chatter">
        ...
    </div>
</div>

この例では、event_streamエンドポイントへのSSE接続を確立し、chatterイベントが表示されるたびに/chatroom URLへのGETをトリガーします。

自動再接続

SSE Event Streamが予期せず閉じられた場合、ブラウザは自動的に再接続を試みる必要があります。ただし、まれにこれは機能せず、ブラウザがハングする可能性があります。この拡張機能は、ブラウザの自動再接続の上に独自の再接続ロジック(指数バックオフアルゴリズムを使用)を追加するため、SSEストリームは常に可能な限り信頼できるものになります。

デモサーバーを使用したSSE接続のテスト

Htmxには、Node.jsで記述されたデモSSEサーバーが含まれており、SSEの動作を確認し、独自のSSEコードのブートストラップを開始するのに役立ちます。htmx配布の/test/ws-sseフォルダーにあります。/test/ws-sse/README.mdで、テストサーバーの実行と使用に関する手順を確認してください。

以前のバージョンからの移行

以前のバージョンのhtmxは、組み込みタグhx-sseを使用してサーバー送信イベントを実装していました。このコードは拡張機能に移行されました。このバージョンに移行するために必要な手順を以下に示します。

古い属性新しい属性コメント
hx-sse=""hx-ext="sse"hx-ext="sse"属性を使用して、任意のHTML要素にSSE拡張機能をインストールします。
hx-sse="connect:<url>"sse-connect="<url>"Event StreamのURLを指定する新しい属性sse-connectをタグに追加します。この属性は、hx-ext属性と同じタグになければなりません。
hx-sse="swap:<EventName>"sse-swap="<EventName>"SSE拡張機能を介して交換される要素に新しい属性sse-swapを追加します。この属性は、hx-ext属性を含むタグの**上**または**内**に配置する必要があります。
hx-trigger="sse:<EventName>"変更なしhx-trigger属性は変更する必要はありません。拡張機能はこれらの属性を識別し、sse:で始まるイベントのリスナーを追加します。

この拡張機能によってディスパッチされたイベントのリッスン

この拡張機能はいくつかのイベントをディスパッチします。これらのイベントは次のようにリッスンできます。

document.body.addEventListener('htmx:sseBeforeMessage', function (e) {
    // do something before the event data is swapped in
})

各イベントオブジェクトには、イベントの詳細を含むdetailフィールドがあります。

htmx:sseOpen

このイベントは、SSE接続が正常に確立されたときにディスパッチされます。

詳細

htmx:sseError

このイベントは、SSE接続を確立できなかったときにディスパッチされます。

詳細

htmx:sseBeforeMessage

このイベントは、SSEイベントデータがDOMにスワップされる直前にディスパッチされます。スワップしたくない場合は、イベントでpreventDefault()を呼び出します。さらに、detailフィールドはMessageEventです。これは、SSEメッセージを受信したときにEventSourceによって作成されたイベントです。

詳細

htmx:sseMessage

このイベントは、SSEイベントデータがDOMにスワップされた後にディスパッチされます。detailフィールドはMessageEventです。これは、SSEメッセージを受信したときにEventSourceによって作成されたイベントです。

htmx:sseClose

このイベントは、3つの異なるクローズシナリオでディスパッチされます。シナリオを制御するために、ユーザーはevt.detail.ssecloseプロパティを制御できます。

document.body.addEventListener('htmx:sseClose', function (e) {
    const reason = e.detail.type
    switch (reason) {
        case "nodeMissing":
            // Parent node is missing and therefore connection was closed
        ...
        case "nodeReplaced":
            // Parent node replacement caused closing of connection
        ...
        case "message":
            // connection was closed due to reception of message sse-close
        ...
    }
})
詳細

追加のSSEリソース