Improve hx-ws messages and reconnects - #3910
Conversation
58579bd to
2dbff37
Compare
2dbff37 to
1b55733
Compare
68ecf49 to
48472eb
Compare
hx-ws messages and reconnects
…ii-comment # Conflicts: # src/ext/hx-ws.js
|
Good work on this. The element-owned connections and lifecycle events fix the orphan/pending-cleanup issues from the 4.0/ws-alignment review properly instead of patching around them, and waitUntil() is a nice addition. A few thoughts on message handling. These are direction questions rather than implementation ones: 1. Should incoming fragments be addressed by ID instead of resolved by content?Right now messages with target/content/swap fields trigger target resolution plus swap logic, with the swap:none fallback when they're absent. An alternative worth considering: if the payload carries an element ID, morph or replace that element by ID and skip target resolution entirely. That makes the routing model uniform. Messages address elements, elements own connections. It pairs naturally with the new ownership model, and it lets servers send idempotent patches without caring what was previously in the DOM. Probably not for this PR, but if the wire format is changing anyway (HX-Request-ID removal), this is the cheapest time to reserve a shape for it. 2. Versioning the outgoing wire formatWith the correlation system gone, servers speaking the old protocol will silently degrade. A type field or version header on outbound messages would let backends detect and adapt, and gives room for future message kinds without magic-field sniffing. Even a small closed vocabulary, fragment / event, makes both client dispatch and the server-side story easier to document. 3. Connection-per-element trade-offElement ownership fixes the orphan bug, but a page with several hx-ws:connect elements now holds several sockets to the same URL. Worth a docs note on the expected pattern (one connection element per page, listeners attach to it) so people don't accidentally fan out sockets. And if shared connections ever come back, element-ID-addressed routing is what makes sharing safe again. Another argument for reserving that shape. The implementation itself is solid. These are mostly about locking in the wire format before it calcifies. |
Redesign
hx-wsaround element-owned connections and one lifecycle for incoming and outgoing messages.Messages stay ordered while sockets open or reconnect, like in htmx 2.0. Only configured close codes retry. Sender correlation and URL pooling are removed.
Connections
hx-ws:senduses the nearesthx-ws:connect, including one on the same element.An
hx-ws:sendvalue no longer opens a connection and is ignored, matching htmx 2.0'sws-sendmarker. Puthx-ws:connecton the same element to make the sender own its connection.Messages
Both directions use:
Before hooks can:
waitUntil(promise).event.preventDefault()ordetail.cancelled = true.message.data.Format
Outgoing values move from
bodyto the top level:Events
htmx:before:ws:connectionhtmx:ws:before:connectionhtmx:after:ws:connectionhtmx:ws:after:connectionhtmx:before:ws:requesthtmx:ws:before:message:outgoinghtmx:after:ws:requesthtmx:ws:after:message:outgoinghtmx:before:ws:messagehtmx:ws:before:message:incominghtmx:after:ws:messagehtmx:ws:after:message:incominghtmx:ws:erroridentifies an existingconnection, or the requestedurlwhen no connection exists.Order
ws.maxOutgoingMessagesQueueSizebounds the queue.This restores htmx 2's queue behavior.
Reconnect
Reconnect requires:
ws.reconnectenabled.ws.reconnectCodes.Code
1000stops by default. A later trigger can open a new connection.Config comes from global
htmx.config.wsand localhx-configvalues.Correlation
Removed:
HX-Request-IDrouting.request_idrouting.Incoming messages use the connection owner.