فهرست منبع

fix the fullstack platform with the new launch API

Evan Almloff 1 سال پیش
والد
کامیت
a323962a22

+ 16 - 1
packages/desktop/src/launch.rs

@@ -11,7 +11,7 @@ use tao::event::{Event, StartCause, WindowEvent};
 ///
 /// This will block the main thread, and *must* be spawned on the main thread. This function does not assume any runtime
 /// and is equivalent to calling launch_with_props with the tokio feature disabled.
-pub fn launch_with_props_blocking(virtual_dom: VirtualDom, desktop_config: Config) {
+pub fn launch_virtual_dom_blocking(virtual_dom: VirtualDom, desktop_config: Config) {
     let (event_loop, mut app) = App::new(desktop_config, virtual_dom);
 
     event_loop.run(move |window_event, _, control_flow| {
@@ -48,6 +48,21 @@ pub fn launch_with_props_blocking(virtual_dom: VirtualDom, desktop_config: Confi
     })
 }
 
+/// Launches the WebView and runs the event loop, with configuration and root props.
+pub fn launch_virtual_dom(virtual_dom: VirtualDom, desktop_config: Config) {
+    #[cfg(feature = "tokio")]
+    tokio::runtime::Builder::new_multi_thread()
+        .enable_all()
+        .build()
+        .unwrap()
+        .block_on(tokio::task::unconstrained(async move {
+            launch_virtual_dom_blocking(virtual_dom, desktop_config)
+        }));
+
+    #[cfg(not(feature = "tokio"))]
+    launch_virtual_dom_blocking(config, desktop_config)
+}
+
 /// Launches the WebView and runs the event loop, with configuration and root props.
 pub fn launch(
     root: fn() -> Element,

+ 18 - 16
packages/fullstack/src/adapters/axum_adapter.rs

@@ -63,7 +63,8 @@ use axum::{
     routing::{get, post},
     Router,
 };
-use dioxus_lib::prelude::dioxus_core::{AnyProps, CrossPlatformConfig};
+use dioxus_lib::prelude::dioxus_core::AnyProps;
+use dioxus_lib::prelude::VirtualDom;
 use server_fn::{Encoding, ServerFunctionRegistry};
 use std::sync::Arc;
 use std::sync::RwLock;
@@ -216,11 +217,11 @@ pub trait DioxusRouterExt<S> {
     ///     todo!()
     /// }
     /// ```
-    fn serve_dioxus_application<P: AnyProps + Clone + Send + Sync + 'static>(
+    fn serve_dioxus_application(
         self,
         server_fn_route: &'static str,
         cfg: impl Into<ServeConfig>,
-        dioxus_config: CrossPlatformConfig<P>,
+        build_virtual_dom: impl Fn() -> VirtualDom + Send + Sync + 'static,
     ) -> Self;
 }
 
@@ -315,11 +316,11 @@ where
         self
     }
 
-    fn serve_dioxus_application<P: AnyProps + Clone + Send + Sync + 'static>(
+    fn serve_dioxus_application(
         self,
         server_fn_route: &'static str,
         cfg: impl Into<ServeConfig>,
-        dioxus_config: CrossPlatformConfig<P>,
+        build_virtual_dom: impl Fn() -> VirtualDom + Send + Sync + 'static,
     ) -> Self {
         let cfg = cfg.into();
         let ssr_state = SSRState::new(&cfg);
@@ -328,7 +329,7 @@ where
         self.serve_static_assets(cfg.assets_path)
             .connect_hot_reload()
             .register_server_fns(server_fn_route)
-            .fallback(get(render_handler).with_state((cfg, dioxus_config, ssr_state)))
+            .fallback(get(render_handler).with_state((cfg, Arc::new(build_virtual_dom), ssr_state)))
     }
 
     fn connect_hot_reload(self) -> Self {
@@ -418,15 +419,12 @@ fn apply_request_parts_to_response<B>(
 ///         .unwrap();
 /// }
 /// ```
-pub async fn render_handler_with_context<
-    P: AnyProps + Clone + Send + Sync + 'static,
-    F: FnMut(&mut DioxusServerContext),
->(
-    State((mut inject_context, cfg, ssr_state, dioxus_config)): State<(
+pub async fn render_handler_with_context<F: FnMut(&mut DioxusServerContext)>(
+    State((mut inject_context, cfg, ssr_state, virtual_dom_factory)): State<(
         F,
         ServeConfig,
         SSRState,
-        CrossPlatformConfig<P>,
+        Arc<dyn Fn() -> VirtualDom + Send + Sync>,
     )>,
     request: Request<Body>,
 ) -> impl IntoResponse {
@@ -437,7 +435,7 @@ pub async fn render_handler_with_context<
     inject_context(&mut server_context);
 
     match ssr_state
-        .render(url, &cfg, dioxus_config, &server_context)
+        .render(url, &cfg, move || virtual_dom_factory(), &server_context)
         .await
     {
         Ok(rendered) => {
@@ -456,12 +454,16 @@ pub async fn render_handler_with_context<
 }
 
 /// SSR renderer handler for Axum
-pub async fn render_handler<P: AnyProps + Clone + Send + Sync + 'static>(
-    State((cfg, dioxus_config, ssr_state)): State<(ServeConfig, CrossPlatformConfig<P>, SSRState)>,
+pub async fn render_handler(
+    State((cfg, virtual_dom_factory, ssr_state)): State<(
+        ServeConfig,
+        Arc<dyn Fn() -> VirtualDom + Send + Sync>,
+        SSRState,
+    )>,
     request: Request<Body>,
 ) -> impl IntoResponse {
     render_handler_with_context(
-        State((|_: &mut _| (), cfg, ssr_state, dioxus_config)),
+        State((|_: &mut _| (), cfg, ssr_state, virtual_dom_factory)),
         request,
     )
     .await

+ 206 - 0
packages/fullstack/src/config.rs

@@ -0,0 +1,206 @@
+//! Launch helper macros for fullstack apps
+#![allow(unused)]
+use crate::prelude::*;
+use dioxus_lib::prelude::{dioxus_core::AnyProps, *};
+use std::sync::Arc;
+
+/// Settings for a fullstack app.
+pub struct Config {
+    #[cfg(feature = "ssr")]
+    server_fn_route: &'static str,
+    #[cfg(feature = "ssr")]
+    server_cfg: ServeConfigBuilder,
+    #[cfg(feature = "ssr")]
+    addr: std::net::SocketAddr,
+    #[cfg(feature = "web")]
+    web_cfg: dioxus_web::Config,
+    #[cfg(feature = "desktop")]
+    desktop_cfg: dioxus_desktop::Config,
+}
+
+#[allow(clippy::derivable_impls)]
+impl Default for Config {
+    fn default() -> Self {
+        Self {
+            #[cfg(feature = "ssr")]
+            server_fn_route: "",
+            #[cfg(feature = "ssr")]
+            addr: std::net::SocketAddr::from(([127, 0, 0, 1], 8080)),
+            #[cfg(feature = "ssr")]
+            server_cfg: ServeConfigBuilder::new(),
+            #[cfg(feature = "web")]
+            web_cfg: dioxus_web::Config::default(),
+            #[cfg(feature = "desktop")]
+            desktop_cfg: dioxus_desktop::Config::default(),
+        }
+    }
+}
+
+impl Config {
+    /// Create a new config for a fullstack app.
+    pub fn new() -> Self {
+        Self::default()
+    }
+
+    /// Set the address to serve the app on.
+    #[cfg(feature = "ssr")]
+    pub fn addr(self, addr: impl Into<std::net::SocketAddr>) -> Self {
+        let addr = addr.into();
+        Self { addr, ..self }
+    }
+
+    /// Set the route to the server functions.
+    #[cfg(feature = "ssr")]
+    pub fn server_fn_route(self, server_fn_route: &'static str) -> Self {
+        Self {
+            server_fn_route,
+            ..self
+        }
+    }
+
+    /// Set the incremental renderer config.
+    #[cfg(feature = "ssr")]
+    pub fn incremental(self, cfg: IncrementalRendererConfig) -> Self {
+        Self {
+            server_cfg: self.server_cfg.incremental(cfg),
+            ..self
+        }
+    }
+
+    /// Set the server config.
+    #[cfg(feature = "ssr")]
+    pub fn server_cfg(self, server_cfg: ServeConfigBuilder) -> Self {
+        Self { server_cfg, ..self }
+    }
+
+    /// Set the web config.
+    #[cfg(feature = "web")]
+    pub fn web_cfg(self, web_cfg: dioxus_web::Config) -> Self {
+        Self { web_cfg, ..self }
+    }
+
+    /// Set the desktop config.
+    #[cfg(feature = "desktop")]
+    pub fn desktop_cfg(self, desktop_cfg: dioxus_desktop::Config) -> Self {
+        Self {
+            desktop_cfg,
+            ..self
+        }
+    }
+
+    /// Launch the app.
+    pub fn launch(self, build_virtual_dom: impl Fn() -> VirtualDom + Send + Sync + 'static) {
+        #[cfg(feature = "ssr")]
+        tokio::runtime::Runtime::new()
+            .unwrap()
+            .block_on(async move {
+                self.launch_server(build_virtual_dom).await;
+            });
+        #[cfg(not(feature = "ssr"))]
+        {
+            #[cfg(feature = "web")]
+            self.launch_web(build_virtual_dom);
+            #[cfg(feature = "desktop")]
+            self.launch_desktop(build_virtual_dom);
+        }
+    }
+
+    #[cfg(feature = "web")]
+    /// Launch the web application
+    pub fn launch_web(self, build_virtual_dom: impl Fn() -> VirtualDom + Send + Sync + 'static) {
+        #[cfg(not(feature = "ssr"))]
+        {
+            let cfg = self.web_cfg.hydrate(true);
+            dioxus_web::run(
+                // TODO: this should pull the props from the document
+                build_virtual_dom(),
+                cfg,
+            );
+        }
+    }
+
+    #[cfg(feature = "desktop")]
+    /// Launch the web application
+    pub fn launch_desktop<P: AnyProps>(self, build_virtual_dom: impl Fn() -> VirtualDom + 'static) {
+        let cfg = self.desktop_cfg;
+        dioxus_desktop::launch::launch_with_props_blocking(self.component, self.props, cfg);
+    }
+
+    #[cfg(feature = "ssr")]
+    /// Launch a server application
+    pub async fn launch_server(
+        self,
+        build_virtual_dom: impl Fn() -> VirtualDom + Send + Sync + 'static,
+    ) {
+        let addr = self.addr;
+        println!("Listening on {}", addr);
+        let cfg = self.server_cfg.build();
+        let server_fn_route = self.server_fn_route;
+        #[cfg(all(feature = "axum", not(feature = "warp"), not(feature = "salvo")))]
+        {
+            use crate::adapters::axum_adapter::{render_handler, DioxusRouterExt};
+            use axum::routing::get;
+            use tower::ServiceBuilder;
+
+            let ssr_state = SSRState::new(&cfg);
+            let router = axum::Router::new().register_server_fns(server_fn_route);
+            #[cfg(not(feature = "desktop"))]
+            let router = router
+                .serve_static_assets(cfg.assets_path)
+                .connect_hot_reload()
+                .fallback(get(render_handler).with_state((
+                    cfg,
+                    Arc::new(build_virtual_dom),
+                    ssr_state,
+                )));
+            let router = router
+                .layer(
+                    ServiceBuilder::new()
+                        .layer(tower_http::compression::CompressionLayer::new().gzip(true)),
+                )
+                .into_make_service();
+            axum::Server::bind(&addr).serve(router).await.unwrap();
+        }
+        #[cfg(all(feature = "warp", not(feature = "axum"), not(feature = "salvo")))]
+        {
+            use warp::Filter;
+            // First register the server functions
+            let router = register_server_fns(server_fn_route);
+            #[cfg(not(feature = "desktop"))]
+            let router = {
+                // Serve the dist folder and the index.html file
+                let serve_dir = warp::fs::dir(cfg.assets_path);
+
+                router
+                    .or(connect_hot_reload())
+                    // Then the index route
+                    .or(warp::path::end().and(render_ssr(cfg.clone())))
+                    // Then the static assets
+                    .or(serve_dir)
+                    // Then all other routes
+                    .or(render_ssr(cfg))
+            };
+            warp::serve(router.boxed().with(warp::filters::compression::gzip()))
+                .run(addr)
+                .await;
+        }
+        #[cfg(all(feature = "salvo", not(feature = "axum"), not(feature = "warp")))]
+        {
+            use crate::adapters::salvo_adapter::{DioxusRouterExt, SSRHandler};
+            use salvo::conn::Listener;
+            let router = salvo::Router::new().register_server_fns(server_fn_route);
+            #[cfg(not(feature = "desktop"))]
+            let router = router
+                .serve_static_assets(cfg.assets_path)
+                .connect_hot_reload()
+                .push(salvo::Router::with_path("/<**any_path>").get(SSRHandler::new(cfg)));
+            let router = router.hoop(
+                salvo::compression::Compression::new()
+                    .enable_gzip(salvo::prelude::CompressionLevel::Default),
+            );
+            salvo::Server::new(salvo::conn::tcp::TcpListener::new(addr).bind().await)
+                .serve(router)
+                .await;
+        }
+    }
+}

+ 33 - 230
packages/fullstack/src/launch.rs

@@ -1,232 +1,35 @@
-//! Launch helper macros for fullstack apps
-#![allow(unused)]
-use crate::prelude::*;
-use dioxus_lib::prelude::{
-    dioxus_core::{AnyProps, CrossPlatformConfig},
-    *,
-};
-
-pub mod launch {
-    use dioxus_lib::prelude::{dioxus_core::BoxedContext, Element, VirtualDom};
-
-    pub type Config = crate::Config;
-
-    pub fn launch(
-        root: fn() -> Element,
-        contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send>>,
-        platform_config: Config,
-    ) {
-        #[cfg(feature = "ssr")]
-        tokio::runtime::Runtime::new()
-            .unwrap()
-            .block_on(async move {
-                platform_config.launch_server(config).await;
-            });
-        #[cfg(not(feature = "ssr"))]
-        {
-            #[cfg(feature = "web")]
-            platform_config.launch_web(dom);
-            #[cfg(feature = "desktop")]
-            platform_config.launch_desktop(dom);
-        }
-    }
-}
-
-/// Settings for a fullstack app.
-pub struct Config {
-    #[cfg(feature = "ssr")]
-    server_fn_route: &'static str,
-    #[cfg(feature = "ssr")]
-    server_cfg: ServeConfigBuilder,
-    #[cfg(feature = "ssr")]
-    addr: std::net::SocketAddr,
-    #[cfg(feature = "web")]
-    web_cfg: dioxus_web::Config,
-    #[cfg(feature = "desktop")]
-    desktop_cfg: dioxus_desktop::Config,
-}
-
-#[allow(clippy::derivable_impls)]
-impl Default for Config {
-    fn default() -> Self {
-        Self {
-            #[cfg(feature = "ssr")]
-            server_fn_route: "",
-            #[cfg(feature = "ssr")]
-            addr: std::net::SocketAddr::from(([127, 0, 0, 1], 8080)),
-            #[cfg(feature = "ssr")]
-            server_cfg: ServeConfigBuilder::new(),
-            #[cfg(feature = "web")]
-            web_cfg: dioxus_web::Config::default(),
-            #[cfg(feature = "desktop")]
-            desktop_cfg: dioxus_desktop::Config::default(),
-        }
-    }
-}
-
-impl Config {
-    /// Create a new config for a fullstack app.
-    pub fn new() -> Self {
-        Self::default()
-    }
-
-    /// Set the address to serve the app on.
-    #[cfg(feature = "ssr")]
-    pub fn addr(self, addr: impl Into<std::net::SocketAddr>) -> Self {
-        let addr = addr.into();
-        Self { addr, ..self }
-    }
-
-    /// Set the route to the server functions.
-    #[cfg(feature = "ssr")]
-    pub fn server_fn_route(self, server_fn_route: &'static str) -> Self {
-        Self {
-            server_fn_route,
-            ..self
-        }
-    }
-
-    /// Set the incremental renderer config.
-    #[cfg(feature = "ssr")]
-    pub fn incremental(self, cfg: IncrementalRendererConfig) -> Self {
-        Self {
-            server_cfg: self.server_cfg.incremental(cfg),
-            ..self
-        }
-    }
-
-    /// Set the server config.
-    #[cfg(feature = "ssr")]
-    pub fn server_cfg(self, server_cfg: ServeConfigBuilder) -> Self {
-        Self { server_cfg, ..self }
-    }
-
-    /// Set the web config.
-    #[cfg(feature = "web")]
-    pub fn web_cfg(self, web_cfg: dioxus_web::Config) -> Self {
-        Self { web_cfg, ..self }
-    }
-
-    /// Set the desktop config.
-    #[cfg(feature = "desktop")]
-    pub fn desktop_cfg(self, desktop_cfg: dioxus_desktop::Config) -> Self {
-        Self {
-            desktop_cfg,
-            ..self
-        }
-    }
-
-    /// Launch the app.
-    pub fn launch<P: AnyProps + Clone + Send + Sync>(self, dioxus_config: CrossPlatformConfig<P>) {
-        #[cfg(feature = "ssr")]
-        tokio::runtime::Runtime::new()
-            .unwrap()
-            .block_on(async move {
-                self.launch_server(dioxus_config).await;
-            });
-        #[cfg(not(feature = "ssr"))]
-        {
-            #[cfg(feature = "web")]
-            self.launch_web(dioxus_config);
-            #[cfg(feature = "desktop")]
-            self.launch_desktop(dioxus_config);
-        }
-    }
-
-    #[cfg(feature = "web")]
-    /// Launch the web application
-    pub fn launch_web<P: AnyProps>(self, dioxus_config: CrossPlatformConfig<P>) {
-        use dioxus_lib::prelude::dioxus_core::{CrossPlatformConfig, PlatformBuilder};
-
-        #[cfg(not(feature = "ssr"))]
-        {
-            let cfg = self.web_cfg.hydrate(true);
-            dioxus_web::WebPlatform::launch(
-                // TODO: this should pull the props from the document
-                dioxus_config,
-                cfg,
-            );
-        }
-    }
-
-    #[cfg(feature = "desktop")]
-    /// Launch the web application
-    pub fn launch_desktop<P: AnyProps>(self, dioxus_config: CrossPlatformConfig<P>) {
-        let cfg = self.desktop_cfg;
-        dioxus_desktop::launch_with_props(self.component, self.props, cfg);
-    }
-
-    #[cfg(feature = "ssr")]
-    /// Launch a server application
-    pub async fn launch_server<P: AnyProps + Send + Sync + Clone>(
-        self,
-        dioxus_config: CrossPlatformConfig<P>,
-    ) {
-        let addr = self.addr;
-        println!("Listening on {}", addr);
-        let cfg = self.server_cfg.build();
-        let server_fn_route = self.server_fn_route;
-        #[cfg(all(feature = "axum", not(feature = "warp"), not(feature = "salvo")))]
-        {
-            use crate::adapters::axum_adapter::{render_handler, DioxusRouterExt};
-            use axum::routing::get;
-            use tower::ServiceBuilder;
-
-            let ssr_state = SSRState::new(&cfg);
-            let router = axum::Router::new().register_server_fns(server_fn_route);
-            #[cfg(not(feature = "desktop"))]
-            let router = router
-                .serve_static_assets(cfg.assets_path)
-                .connect_hot_reload()
-                .fallback(get(render_handler).with_state((cfg, dioxus_config, ssr_state)));
-            let router = router
-                .layer(
-                    ServiceBuilder::new()
-                        .layer(tower_http::compression::CompressionLayer::new().gzip(true)),
-                )
-                .into_make_service();
-            axum::Server::bind(&addr).serve(router).await.unwrap();
-        }
-        #[cfg(all(feature = "warp", not(feature = "axum"), not(feature = "salvo")))]
-        {
-            use warp::Filter;
-            // First register the server functions
-            let router = register_server_fns(server_fn_route);
-            #[cfg(not(feature = "desktop"))]
-            let router = {
-                // Serve the dist folder and the index.html file
-                let serve_dir = warp::fs::dir(cfg.assets_path);
-
-                router
-                    .or(connect_hot_reload())
-                    // Then the index route
-                    .or(warp::path::end().and(render_ssr(cfg.clone())))
-                    // Then the static assets
-                    .or(serve_dir)
-                    // Then all other routes
-                    .or(render_ssr(cfg))
-            };
-            warp::serve(router.boxed().with(warp::filters::compression::gzip()))
-                .run(addr)
-                .await;
-        }
-        #[cfg(all(feature = "salvo", not(feature = "axum"), not(feature = "warp")))]
-        {
-            use crate::adapters::salvo_adapter::{DioxusRouterExt, SSRHandler};
-            use salvo::conn::Listener;
-            let router = salvo::Router::new().register_server_fns(server_fn_route);
-            #[cfg(not(feature = "desktop"))]
-            let router = router
-                .serve_static_assets(cfg.assets_path)
-                .connect_hot_reload()
-                .push(salvo::Router::with_path("/<**any_path>").get(SSRHandler::new(cfg)));
-            let router = router.hoop(
-                salvo::compression::Compression::new()
-                    .enable_gzip(salvo::prelude::CompressionLevel::Default),
-            );
-            salvo::Server::new(salvo::conn::tcp::TcpListener::new(addr).bind().await)
-                .serve(router)
-                .await;
-        }
+//! This module contains the `launch` function, which is the main entry point for dioxus fullstack
+
+use std::any::Any;
+
+use dioxus_lib::prelude::{Element, VirtualDom};
+
+pub use crate::Config;
+
+/// Launch a fullstack app with the given root component, contexts, and config.
+pub fn launch(
+    root: fn() -> Element,
+    contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
+    platform_config: Config,
+) {
+    let virtual_dom_factory = move || {
+        let mut vdom = VirtualDom::new(root);
+        for context in &contexts {
+            vdom.insert_any_root_context(context());
+        }
+        vdom
+    };
+    #[cfg(feature = "ssr")]
+    tokio::runtime::Runtime::new()
+        .unwrap()
+        .block_on(async move {
+            platform_config.launch_server(virtual_dom_factory).await;
+        });
+    #[cfg(not(feature = "ssr"))]
+    {
+        #[cfg(feature = "web")]
+        platform_config.launch_web(virtual_dom_factory);
+        #[cfg(feature = "desktop")]
+        platform_config.launch_desktop(virtual_dom_factory);
     }
 }

+ 3 - 2
packages/fullstack/src/lib.rs

@@ -11,11 +11,12 @@ mod html_storage;
 mod adapters;
 #[cfg(feature = "ssr")]
 pub use adapters::*;
+mod config;
 mod hooks;
 #[cfg(all(debug_assertions, feature = "hot-reload", feature = "ssr"))]
 mod hot_reload;
-mod launch;
-pub use launch::*;
+pub mod launch;
+pub use config::*;
 #[cfg(feature = "ssr")]
 mod layer;
 #[cfg(feature = "ssr")]

+ 7 - 8
packages/fullstack/src/render.rs

@@ -1,6 +1,5 @@
 //! A shared pool of renderers for efficient server side rendering.
 use crate::render::dioxus_core::AnyProps;
-use crate::render::dioxus_core::CrossPlatformConfig;
 use crate::render::dioxus_core::NoOpMutations;
 use crate::server_context::SERVER_CONTEXT;
 use dioxus_lib::prelude::VirtualDom;
@@ -22,11 +21,11 @@ enum SsrRendererPool {
 }
 
 impl SsrRendererPool {
-    async fn render_to<P: AnyProps + Clone + Send + Sync + 'static>(
+    async fn render_to(
         &self,
         cfg: &ServeConfig,
         route: String,
-        dioxus_config: CrossPlatformConfig<P>,
+        virtual_dom_factory: impl FnOnce() -> VirtualDom + Send + Sync + 'static,
         server_context: &DioxusServerContext,
     ) -> Result<(RenderFreshness, String), dioxus_ssr::incremental::IncrementalRendererError> {
         let wrapper = FullstackRenderer {
@@ -45,7 +44,7 @@ impl SsrRendererPool {
                     tokio::runtime::Runtime::new()
                         .expect("couldn't spawn runtime")
                         .block_on(async move {
-                            let mut vdom = dioxus_config.build_vdom();
+                            let mut vdom = virtual_dom_factory();
                             vdom.in_runtime(|| {
                                 // Make sure the evaluator is initialized
                                 dioxus_ssr::eval::init_eval();
@@ -112,7 +111,7 @@ impl SsrRendererPool {
                             match renderer
                                 .render(
                                     route,
-                                    dioxus_config,
+                                    virtual_dom_factory,
                                     &mut *to,
                                     |vdom| {
                                         Box::pin(async move {
@@ -192,11 +191,11 @@ impl SSRState {
     }
 
     /// Render the application to HTML.
-    pub fn render<'a, P: AnyProps + Clone + Send + Sync>(
+    pub fn render<'a>(
         &'a self,
         route: String,
         cfg: &'a ServeConfig,
-        dioxus_config: CrossPlatformConfig<P>,
+        virtual_dom_factory: impl FnOnce() -> VirtualDom + Send + Sync + 'static,
         server_context: &'a DioxusServerContext,
     ) -> impl std::future::Future<
         Output = Result<RenderResponse, dioxus_ssr::incremental::IncrementalRendererError>,
@@ -207,7 +206,7 @@ impl SSRState {
 
             let (freshness, html) = self
                 .renderers
-                .render_to(cfg, route, dioxus_config, server_context)
+                .render_to(cfg, route, virtual_dom_factory, server_context)
                 .await?;
 
             Ok(RenderResponse { html, freshness })

+ 2 - 2
packages/ssr/src/incremental.rs

@@ -170,7 +170,7 @@ impl IncrementalRenderer {
     pub async fn render<R: WrapBody + Send + Sync>(
         &mut self,
         route: String,
-        virtual_dom: VirtualDom,
+        virtual_dom_factory: impl FnOnce() -> VirtualDom,
         output: &mut (impl AsyncWrite + Unpin + std::marker::Send),
         rebuild_with: impl FnOnce(&mut VirtualDom) -> Pin<Box<dyn Future<Output = ()> + '_>>,
         renderer: &R,
@@ -181,7 +181,7 @@ impl IncrementalRenderer {
         } else {
             // if not, create it
             let freshness = self
-                .render_and_cache(route, virtual_dom, output, rebuild_with, renderer)
+                .render_and_cache(route, virtual_dom_factory(), output, rebuild_with, renderer)
                 .await?;
             tracing::trace!("cache miss");
             Ok(freshness)