#leptos #sse #server #signal #client-server #web-framework #actix-web

leptos_sse

Leptos server signals synced through server-sent-events (SSE)

7 releases

0.3.0 Dec 17, 2023
0.2.0 Sep 30, 2023
0.2.0-beta Aug 23, 2023
0.1.2 Aug 21, 2023

#462 in HTTP server

23 downloads per month

MIT license

23KB
354 lines

Leptos Server Sent Events

GitHub Actions Crates.io docs.rs

Server signals are leptos signals kept in sync with the server through server-sent-events (SSE).

The signals are read-only on the client side, and can be written to by the server. This is useful if you want real-time updates on the UI controlled by the server.

Changes to a signal are sent through a SSE to the client as json patches.

This project is heavily based on leptos_server_signal.

Feature flags

  • ssr: ssr is enabled when rendering the app on the server.
  • actix: integration with the Actix web framework.
  • axum: integration with the Axum web framework.

Example

Cargo.toml

[dependencies]
leptos_sse = "*"
serde = { version = "*", features = ["derive"] }

[features]
ssr = [
  "leptos_sse/ssr",
  "leptos_sse/axum", # or actix
]

Client

use leptos::*;
use leptos_sse::create_sse_signal;
use serde::{Deserialize, Serialize};

#[derive(Clone, Default, Serialize, Deserialize)]
pub struct Count {
    pub value: i32,
}

#[component]
pub fn App() -> impl IntoView {
    // Provide SSE connection
    leptos_sse::provide_sse("http://localhost:3000/sse").unwrap();

    // Create server signal
    let count = create_sse_signal::<Count>("counter");

    view! {
        <h1>"Count: " {move || count().value.to_string()}</h1>
    }
}

If on stable, use count.get().value instead of count().value.

Server (Axum)

#[cfg(feature = "ssr")]
use {
    axum::response::sse::{Event, KeepAlive, Sse},
    futures::stream::Stream,
};

#[cfg(feature = "ssr")]
async fn handle_sse() -> Sse<impl Stream<Item = Result<Event, axum::BoxError>>> {
    use futures::stream;
    use leptos_sse::ServerSentEvents;
    use std::time::Duration;
    use tokio_stream::StreamExt as _;

    let mut value = 0;
    let stream = ServerSentEvents::new(
        "counter",
        stream::repeat_with(move || {
            let curr = value;
            value += 1;
            Ok(Count { value: curr })
        })
        .throttle(Duration::from_secs(1)),
    )
    .unwrap();
    Sse::new(stream).keep_alive(KeepAlive::default())
}

License

This work is released under the MIT license. A copy of the license is provided in the LICENSE file.

Dependencies

~18–34MB
~537K SLoC