htmx Web Socket 扩展

Web Sockets 扩展可以直接从 HTML 轻松实现与 Web 套接字 服务器的双向通信。这取代了 htmx 以前版本中内置的实验性 hx-ws 属性。有关从旧版本迁移的帮助,请参阅本页底部的 迁移 指南。

¥The Web Sockets extension enables easy, bi-directional communication with Web Sockets servers directly from HTML. This replaces the experimental hx-ws attribute built into previous versions of htmx. For help migrating from older versions, see the Migrating guide at the bottom of this page.

使用以下属性配置 WebSockets 的行为方式:

¥Use the following attributes to configure how WebSockets behave:

安装

¥Installing

安装 ws 的最快方法是通过 CDN 加载它。请记住始终在扩展和 启用扩展 之前包含核心 htmx 库。

¥The fastest way to install ws is to load it via a CDN. Remember to always include the core htmx library before the extension and enable the extension.

<head>
    <script src="https://unpkg.com/htmx.org@2.0.4" integrity="sha384-HGfztofotfshcF7+8n44JQL2oJmowVChPTg48S+jvZoztPfvwD79OC/LTtG6dMp+" crossorigin="anonymous"></script>
    <script src="https://unpkg.com/htmx-ext-ws@2.0.2" integrity="sha384-vuKxTKv5TX/b3lLzDKP2U363sOAoRo5wSvzzc3LJsbaQRSBSS+3rKKHcOx5J8doU" crossorigin="anonymous"></script>
</head>
<body hx-ext="ws">

https://unpkg.com/htmx-ext-ws/dist/ws.js 上还有一个未缩小的版本。

¥An unminified version is also available at https://unpkg.com/htmx-ext-ws/dist/ws.js.

虽然 CDN 方法很简单,但你可能需要考虑 在生产中不使用 CDN。安装 ws 的下一个最简单的方法是将其复制到你的项目中。从 https://unpkg.com/htmx-ext-ws 下载扩展,将其添加到项目中的相应目录中,并在必要时使用 <script> 标签将其包含在内。

¥While the CDN approach is simple, you may want to consider not using CDNs in production. The next easiest way to install ws is to simply copy it into your project. Download the extension from https://unpkg.com/htmx-ext-ws, add it to the appropriate directory in your project and include it where necessary with a <script> tag.

对于 npm 样式的构建系统,你可以通过 npm 安装 ws

¥For npm-style build systems, you can install ws via npm:

npm install htmx-ext-ws

安装后,你需要使用适当的工具来打包 node_modules/htmx-ext-ws/dist/ws.js(或 .min.js)。例如,你可以将扩展与来自 node_modules/htmx.org/dist/htmx.js 的 htmx 核心和项目特定代码打包在一起。

¥After installing, you’ll need to use appropriate tooling to bundle node_modules/htmx-ext-ws/dist/ws.js (or .min.js). For example, you might bundle the extension with htmx core from node_modules/htmx.org/dist/htmx.js and project-specific code.

如果你使用打包器来管理你的 javascript(例如 Webpack、Rollup):

¥If you are using a bundler to manage your javascript (e.g. Webpack, Rollup):

import `htmx.org`;
import `htmx-ext-ws`; 

使用

¥Usage


<div hx-ext="ws" ws-connect="/chatroom">
    <div id="notifications"></div>
    <div id="chat_room">
        ...
    </div>
    <form id="form" ws-send>
        <input name="chat_message">
    </form>
</div>

配置

¥Configuration

WebSockets 扩展支持两个配置选项:

¥WebSockets extension support two configuration options:

从 WebSocket 接收消息

¥Receiving Messages from a WebSocket

上面的示例建立了到 /chatroom 端点的 WebSocket。从 websocket 发送的内容将被解析为 HTML 并由 id 属性交换,使用与 带外交换 相同的逻辑。

¥The example above establishes a WebSocket to the /chatroom end point. Content that is sent down from the websocket will be parsed as HTML and swapped in by the id property, using the same logic as Out of Band Swaps.

因此,如果你想更改交换方法(例如,在元素末尾附加内容或将交换委托给扩展),则需要在服务器发送的消息正文中指定。

¥As such, if you want to change the swapping method (e.g., append content at the end of an element or delegate swapping to an extension), you need to specify that in the message body, sent by the server.

<!-- will be interpreted as hx-swap-oob="true" by default -->
<form id="form">
    ...
</form>
<!-- will be appended to #notifications div -->
<div id="notifications" hx-swap-oob="beforeend">
    New message received
</div>
<!-- will be swapped using an extension -->
<div id="chat_room" hx-swap-oob="morphdom">
    ....
</div>

向 WebSocket 发送消息

¥Sending Messages to a WebSocket

在上面的例子中,表单使用 ws-send 属性来指示提交时,表单值应序列化为 JSON 并发送到最近的封闭 WebSocket,在本例中为 /chatroom 端点。

¥In the example above, the form uses the ws-send attribute to indicate that when it is submitted, the form values should be serialized as JSON and send to the nearest enclosing WebSocket, in this case the /chatroom endpoint.

序列化的值将包括一个字段 HEADERS,其中包含通常随 htmx 请求一起提交的标头。

¥The serialized values will include a field, HEADERS, that includes the headers normally submitted with an htmx request.

自动重新连接

¥Automatic Reconnection

如果 WebSocket 由于 Abnormal ClosureService RestartTry Again Later 意外关闭,此扩展将尝试重新连接,直到重新建立连接。

¥If the WebSocket is closed unexpectedly, due to Abnormal Closure, Service Restart or Try Again Later, this extension will attempt to reconnect until the connection is reestablished.

默认情况下,扩展使用全抖动 指数退避算法,它会选择随时间呈指数增长的随机重试延迟。你可以通过将其写入 htmx.config.wsReconnectDelay 来使用不同的算法。此函数接受一个参数,即重试次数,并返回重试前等待的时间(以毫秒为单位)。

¥By default, the extension uses a full-jitter exponential-backoff algorithm that chooses a randomized retry delay that grows exponentially over time. You can use a different algorithm by writing it into htmx.config.wsReconnectDelay. This function takes a single parameter, the number of retries, and returns the time (in milliseconds) to wait before trying again.

// example reconnect delay that you shouldn't use because
// it's not as good as the algorithm that's already in place
htmx.config.wsReconnectDelay = function (retryCount) {
    return retryCount * 1000 // return value in milliseconds
}

扩展还实现了一个简单的排队机制,当套接字不处于 OPEN 状态时,该机制将消息保存在内存中,并在连接恢复后发送它们。

¥The extension also implements a simple queuing mechanism that keeps messages in memory when the socket is not in OPEN state and sends them once the connection is restored.

事件

¥Events

WebSockets 扩展公开了一组事件,允许你观察和自定义其行为。

¥WebSockets extensions exposes a set of events that allow you to observe and customize its behavior.

事件 - htmx:wsConnecting

¥Event - htmx:wsConnecting

当尝试建立与 WebSocket 端点的连接时,会触发此事件。

¥This event is triggered when a connection to a WebSocket endpoint is being attempted.

详细信息

¥Details

事件 - htmx:wsOpen

¥Event - htmx:wsOpen

当建立了与 WebSocket 端点的连接时,会触发此事件。

¥This event is triggered when a connection to a WebSocket endpoint has been established.

详细信息

¥Details

事件 - htmx:wsClose

¥Event - htmx:wsClose

当与 WebSocket 端点的连接已正常关闭时会触发此事件。你可以通过检查 detail.event 属性来检查事件是否由错误引起。

¥This event is triggered when a connection to a WebSocket endpoint has been closed normally. You can check if the event was caused by an error by inspecting detail.event property.

详细信息

¥Details

事件 - htmx:wsError

¥Event - htmx:wsError

当套接字上的 onerror 事件发生时,会触发此事件。

¥This event is triggered when onerror event on a socket is raised.

详细信息

¥Details

事件 - htmx:wsBeforeMessage

¥Event - htmx:wsBeforeMessage

当套接字刚刚收到一条消息时,会触发此事件,类似于 htmx:beforeOnLoad。此事件在任何处理发生之前触发。

¥This event is triggered when a message has just been received by a socket, similar to htmx:beforeOnLoad. This event fires before any processing occurs.

如果事件被取消,则不会发生进一步的处理。

¥If the event is cancelled, no further processing will occur.

事件 - htmx:wsAfterMessage

¥Event - htmx:wsAfterMessage

当 htmx 完全处理了一条消息并且所有更改都已确定时,会触发此事件,类似于 htmx:afterOnLoad

¥This event is triggered when a message has been completely processed by htmx and all changes have been settled, similar to htmx:afterOnLoad.

取消此事件无效。

¥Cancelling this event has no effect.

事件 - htmx:wsConfigSend

¥Event - htmx:wsConfigSend

当准备从 ws-send 元素发送消息时,将触发此事件。与 htmx:configRequest 类似,它允许你在发送之前修改消息。

¥This event is triggered when preparing to send a message from ws-send element. Similarly to htmx:configRequest, it allows you to modify the message before sending.

如果事件被取消,则不会发生进一步的处理,也不会发送任何消息。

¥If the event is cancelled, no further processing will occur and no messages will be sent.

详细信息

¥Details

事件 - htmx:wsBeforeSend

¥Event - htmx:wsBeforeSend

此事件在发送消息前立即触发。这包括来自队列的消息。此时无法修改消息。

¥This event is triggered just before sending a message. This includes messages from the queue. Message can not be modified at this point.

如果事件被取消,消息将从队列中丢弃并且不会发送。

¥If the event is cancelled, the message will be discarded from the queue and not sent.

详细信息

¥Details

事件 - htmx:wsAfterSend

¥Event - htmx:wsAfterSend

此事件在发送消息后立即触发。这包括来自队列的消息。

¥This event is triggered just after sending a message. This includes messages from the queue.

取消事件无效。

¥Cancelling the event has no effect.

详细信息

¥Details

套接字封装器

¥Socket wrapper

你可能会注意到所有事件都公开了 detail.socketWrapper 属性。此封装器包含套接字对象本身和消息队列。它还封装了重新连接算法。它公开了一些成员:

¥You may notice that all events expose detail.socketWrapper property. This wrapper holds the socket object itself and the message queue. It also encapsulates reconnection algorithm. It exposes a few members:

此封装器可用于事件处理程序中,以监视和操作队列(例如,你可以在重新连接时重置队列),以及发送其他消息(例如,如果你想批量发送数据)。fromElt 参数是可选的,当指定时,将在发送消息时触发来自指定元素的相应 websocket 事件,即 htmx:wsBeforeSendhtmx:wsAfterSend 事件。

¥This wrapper can be used in your event handlers to monitor and manipulate the queue (e.g., you can reset the queue when reconnecting), and to send additional messages (e.g., if you want to send data in batches). The fromElt parameter is optional and, when specified, will trigger corresponding websocket events from specified element, namely htmx:wsBeforeSend and htmx:wsAfterSend events when sending your messages.

使用演示服务器进行测试

¥Testing with the Demo Server

Htmx 包含一个用 Node.js 编写的演示 WebSockets 服务器,可帮助你查看 WebSockets 的运行情况,并开始引导你自己的 WebSockets 代码。它位于 htmx-extensions 存储库的 /test/ws-sse 文件夹中。查看 /test/ws-sse/README.md 以获取有关运行和使用测试服务器的说明。

¥Htmx includes a demo WebSockets server written in Node.js that will help you to see WebSockets in action, and begin bootstrapping your own WebSockets code. It is located in the /test/ws-sse folder of the htmx-extensions repository. Look at /test/ws-sse/README.md for instructions on running and using the test server.

从以前的版本迁移

¥Migrating from Previous Versions

以前版本的 htmx 使用内置标记 hx-ws 来实现 WebSockets。此代码已迁移到扩展中。以下是迁移到此版本所需采取的步骤:

¥Previous versions of htmx used a built-in tag hx-ws to implement WebSockets. This code has been migrated into an extension instead. Here are the steps you need to take to migrate to this version:

旧属性新属性评论
hx-ws=""hx-ext="ws"使用 hx-ext="ws" 属性将 WebSockets 扩展安装到任何 HTML 元素中。
hx-ws="connect:<url>"ws-connect="<url>"向定义扩展的标签添加新属性 ws-connect,以指定你正在使用的 WebSockets 服务器的 URL。
hx-ws="send"ws-send=""添加新属性 ws-send 以标记应将数据发送到 WebSocket 服务器的任何子表单