htmx-extensions icon indicating copy to clipboard operation
htmx-extensions copied to clipboard

Feature Request: Allow SSE extension to use a user-defined EventSource object

Open adonespitogo opened this issue 11 months ago • 7 comments

This will allow more control over the behavior of the SSE connection. For instance, I want to implement the fix for this firefox bug where I need to have access to the EventSource object for this to be implemented. This will also fix several issues:

  • https://github.com/bigskysoftware/htmx-extensions/issues/132
  • https://github.com/bigskysoftware/htmx-extensions/issues/27

Another advantage is to be able to add event listeners outside of htmx context.

Also, the number of connections is limited to only 6 when not used in HTTP2, so it would be beneficial to reused an existing connection across multiple independent elements.

Warning: When not used over HTTP/2, SSE suffers from a limitation to the maximum number of open connections, which can be especially painful when opening multiple tabs, as the limit is per browser and is set to a very low number (6). The issue has been marked as "Won't fix" in Chrome and Firefox. This limit is per browser + domain, which means that you can open 6 SSE connections across all of the tabs to www.example1.com and another 6 SSE connections to www.example2.com (per Stack Overflow). When using HTTP/2, the maximum number of simultaneous HTTP streams is negotiated between the server and the client (defaults to 100).

adonespitogo avatar Feb 05 '25 08:02 adonespitogo

Hey, it's not documented (documentation improvement PRs are always welcome btw!), but you should already be able to do it ;

  • The extension creates an EventSource with a basic constructor call: https://github.com/bigskysoftware/htmx-extensions/blob/1b894919bc20a02a09841223d59bc9fe4e870fb8/src/sse/sse.js#L76-L78

  • Though, it calls it through a public API here: https://github.com/bigskysoftware/htmx-extensions/blob/1b894919bc20a02a09841223d59bc9fe4e870fb8/src/sse/sse.js#L24-L27

So, you could already override htmx.createEventSource with a function of your own, you simply need to make sure that your code executes before the SSE extension initializes

Hope this helps!

Telroshan avatar Feb 05 '25 09:02 Telroshan

Hi, @Telroshan thank you for this. Although this works, I'd like to make a PR for this as this looks like a hack. I'd like to have something like:

function createEventSource() {
  return Promise.resolve(new EventSource("/sse-events"));
}
<div hx-ext="sse" sse-create="createEventSource" sse-swap="message">

Let me know if this is something that may get accepted.

adonespitogo avatar Feb 05 '25 12:02 adonespitogo

Hey, it's indeed not documented, which isn't ideal for sure, but it's not a hack don't worry about that, it was designed in this way so that it can be overridden, which is precisely your intent here.

Honestly I don't think adding an extra attribute is very relevant here ;

  • you're going to have a custom function defined in your JS anyway, it's just that instead of window.createEventSource = functtion(url) ... (as you need to expose it to be globally to be callable from teh extension), you'll write htmx.createEventSource = function(url) .... Your code would look exactly the same except that declaration, but the latter doesn't require an extra attribute to setup
  • this would likely involve some const functionName = elt.getAttribute("sse-create"); window[functionName](url) logic inside the extension, which honestly feels way more like a hack to me

However, if you need some async logic here to initialize the event source, it's true that for now, the extension doesn't support an async createEventSource function. I see no reason to oppose to making it promise-compatible where the extension would await the event source if the function is async (and act as it currently does if it's not). So if you are interested in the latter change, I'd say feel free to open a PR for it! But I'm not convinced indeed about the sse-create attribute

Telroshan avatar Feb 06 '25 16:02 Telroshan

If we could make the createEventSource async, it would be very useful for when you need to fetch additional server data via ajax before creating the event source object.

For now, my requirements are already satisfied using the synchronous createEventSource function so I will not be implementing the async feature. I'll draft a PR for the createEventSource documentation later today.

adonespitogo avatar Feb 07 '25 11:02 adonespitogo

Sorry, I can't seem to find the source for the documentation. Please feel free to close this issue as I have a limited time and can no longer work on the documentation part.

adonespitogo avatar Feb 09 '25 06:02 adonespitogo

Yeah we had to run a trick for this to keep the core extensions' documentation be on the main website, if you look at this repo's sse folder, you'll see it instructs you to go to the main repo instead at https://github.com/bigskysoftware/htmx/blob/master/www/content/extensions/sse.md to find the SSE documentation

No worries about the lack of time! I'll keep this issue open as it's an interesting point to solve imho, so if anyone (including future me that may have more time available too!) wants to tackle this and submit PRs, please feel free to do so

Telroshan avatar Feb 10 '25 08:02 Telroshan

#139 Is similar and a fully tested EventSource replacement I use in production. (Unsure if it removes any browser connection limits though.)

Just dealing with some chaos with launching my startup. I should be able to tackle this in a few months.

XChikuX avatar Feb 17 '25 07:02 XChikuX