Server-Side Rendering
For lower-level control over the rendering process, you can use the dioxus-ssr
crate directly. This can be useful when integrating with a web framework that dioxus-fullstack
does not support, or pre-rendering pages.
Setup
For this guide, we're going to show how to use Dioxus SSR with Axum.
Make sure you have Rust and Cargo installed, and then create a new project:
cargo new --bin demo cd demo
Add Dioxus and the ssr renderer as dependencies:
cargo add dioxus@0.5.0 cargo add dioxus-ssr@0.5.0
Next, add all the Axum dependencies. This will be different if you're using a different Web Framework
cargo add tokio --features full cargo add axum
Your dependencies should look roughly like this:
[dependencies] axum = "0.7" dioxus = { version = "*" } dioxus-ssr = { version = "*" } tokio = { version = "1.15.0", features = ["full"] }
Now, set up your Axum app to respond on an endpoint.
use axum::{response::Html, routing::get, Router}; use dioxus::prelude::*; #[tokio::main] async fn main() { let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") .await .unwrap(); println!("listening on http://127.0.0.1:3000"); axum::serve( listener, Router::new() .route("/", get(app_endpoint)) .into_make_service(), ) .await .unwrap(); }
And then add our endpoint. We can either render rsx!
directly:
async fn app_endpoint() -> Html<String> { // render the rsx! macro to HTML Html(dioxus_ssr::render_element(rsx! { div { "hello world!" } })) }
Or we can render VirtualDoms.
async fn app_endpoint() -> Html<String> { // create a component that renders a div with the text "hello world" fn app() -> Element { rsx! { div { "hello world" } } } // create a VirtualDom with the app component let mut app = VirtualDom::new(app); // rebuild the VirtualDom before rendering app.rebuild_in_place(); // render the VirtualDom to HTML Html(dioxus_ssr::render(&app)) }
Finally, you can run it using cargo run
rather than dx serve
.
Multithreaded Support
The Dioxus VirtualDom, sadly, is not currently Send
. Internally, we use quite a bit of interior mutability which is not thread-safe.Send
, it is possible to render a VirtualDom immediately to a String – but you cannot hold the VirtualDom across an await point. For retained-state SSR (essentially LiveView), you'll need to spawn a VirtualDom on its own thread and communicate with it via channels or create a pool of VirtualDoms.must remain on the thread it started. We are working on loosening this requirement.