getludic / ludic

🌳 Web Development in Pure Python with Type-Guided Components.
https://getludic.dev
MIT License
730 stars 12 forks source link

Validate SSE support and add page aboutit to the documentation #6

Open paveldedik opened 6 months ago

johanfforsberg commented 3 months ago

I tried SSE using sse-starlette and hx_sse and it works fine as far as I can tell! Do you intend to integrate it further than that?

hx-sse will go away in HTMX 2.0 though, so some changes will be needed: https://htmx.org/extensions/server-sent-events/

paveldedik commented 3 months ago

Thank you very much for testing it. I'm glad to hear that it works! I would like to integrate it further. I'll soon create a roadmap and this will be close to the top (I want to finish new version of documentation first, it will be done soon). I noticed HTMX 2.0 and yeah, I definitely want to figure out how to add proper support in Ludic. I'm not sure how the API will be designed though.

johanfforsberg commented 3 months ago

Interesting! It was a little fiddly; adding the right HTMX attributes in the correct places, and creating SSE endpoints. But on the other hand it's flexible, and I found that I could just send Ludic html in events (guess due to it having a string representation). Probably some common usage patterns could benefit from more integration.

paveldedik commented 3 months ago

Could you share the code you wrote? I'm curious, and I agree, common usage patterns are a good idea.

johanfforsberg commented 3 months ago

Sure, here's a minimal example:

import asyncio

import ludic.html as h
from ludic.web import LudicApp
from sse_starlette.sse import EventSourceResponse, ServerSentEvent

app = LudicApp(debug=True)

@app.get("/")
async def index() -> h:
    return h.html(
        h.body(
            h.div(hx_sse="connect:/events swap:message"),
            h.script(src="https://unpkg.com/htmx.org@1.9.12"),
        ),
    )

async def count():
    value = 0
    while True:
        yield ServerSentEvent(data=value)
        value += 1
        await asyncio.sleep(1)

async def sse():
    return EventSourceResponse(count())

app.add_route("/events", sse)
paveldedik commented 3 months ago

Thank you very much. That is a nice sample, with a bit of testing from my side I'll probably add that to the documentation signed with you as the author of the commit if you don't mind. I also want to check the SSE support in HTMX 2.0 first.

johanfforsberg commented 3 months ago

My pleasure!

I found that I had overcomplicated my use case and probably I should stick with something quite similar to this example in the end. As far as I understand it, with HTTP2 all SSE connections will be "multiplexed" over one connection anyway, so there's little point to trying to collect several subscriptions into one, which was what made it complicated.