浏览代码

collect templates for hot reloading

Evan Almloff 2 年之前
父节点
当前提交
f96425e425
共有 2 个文件被更改,包括 78 次插入50 次删除
  1. 7 1
      packages/server/Cargo.toml
  2. 71 49
      packages/server/src/render.rs

+ 7 - 1
packages/server/Cargo.toml

@@ -6,6 +6,7 @@ edition = "2021"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
+# server functions
 server_fn = { path = "D:/Users/Desktop/github/leptos/server_fn", features = ["stable"] }
 server_macro = { path = "server-macro" }
 
@@ -23,6 +24,7 @@ axum-macros = "0.3.7"
 salvo = { version = "0.37.7", optional = true, features = ["serve-static"] }
 serde = "1.0.159"
 
+# Dioxus + SSR
 dioxus-core = { path = "../core", version = "^0.3.0" }
 dioxus-ssr = { path = "../ssr", version = "^0.3.0", optional = true }
 
@@ -33,8 +35,12 @@ tokio = { version = "1.27.0", features = ["full"], optional = true }
 object-pool = "0.5.4"
 anymap = "0.12.1"
 
+[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
+dioxus-hot-reload = { path = "../hot-reload" }
+
 [features]
-default = []
+default = ["hot-reload"]
+hot-reload = []
 warp = ["dep:warp", "http-body", "ssr"]
 axum = ["dep:axum", "tower-http", "hyper", "ssr"]
 salvo = ["dep:salvo", "hyper", "ssr"]

+ 71 - 49
packages/server/src/render.rs

@@ -6,40 +6,82 @@ use dioxus_ssr::Renderer;
 
 use crate::prelude::ServeConfig;
 
-fn dioxus_ssr_html<P: 'static + Clone>(cfg: &ServeConfig<P>, renderer: &mut Renderer) -> String {
-    let ServeConfig {
-        app,
-        application_name,
-        base_path,
-        head,
-        props,
-        ..
-    } = cfg;
-
-    let mut vdom = VirtualDom::new_with_props(*app, props.clone());
-    let _ = vdom.rebuild();
-
-    let mut html = String::new();
-
-    let result = write!(
-        &mut html,
-        r#"
+#[derive(Clone)]
+pub struct SSRState {
+    // We keep a cache of renderers to avoid re-creating them on every request. They are boxed to make them very cheap to move
+    renderers: Arc<object_pool::Pool<Renderer>>,
+    #[cfg(all(debug_assertions, feature = "hot-reload"))]
+    // The cache of all templates that have been modified since the last time we checked
+    templates: Arc<std::sync::RwLock<std::collections::HashSet<dioxus_core::Template<'static>>>>,
+}
+
+impl Default for SSRState {
+    fn default() -> Self {
+        #[cfg(all(debug_assertions, feature = "hot-reload"))]
+        let templates = {
+            let templates = Arc::new(std::sync::RwLock::new(std::collections::HashSet::new()));
+            dioxus_hot_reload::connect({
+                let templates = templates.clone();
+                move |msg| match msg {
+                    dioxus_hot_reload::HotReloadMsg::UpdateTemplate(template) => {
+                        if let Ok(mut templates) = templates.write() {
+                            templates.insert(template);
+                        }
+                    }
+                    dioxus_hot_reload::HotReloadMsg::Shutdown => {
+                        std::process::exit(0);
+                    }
+                }
+            });
+            templates
+        };
+
+        Self {
+            renderers: Arc::new(object_pool::Pool::new(10, pre_renderer)),
+            #[cfg(all(debug_assertions, feature = "hot-reload"))]
+            templates,
+        }
+    }
+}
+
+impl SSRState {
+    pub fn render<P: 'static + Clone>(&self, cfg: &ServeConfig<P>) -> String {
+        let ServeConfig {
+            app,
+            application_name,
+            base_path,
+            head,
+            props,
+            ..
+        } = cfg;
+
+        let mut vdom = VirtualDom::new_with_props(*app, props.clone());
+
+        let _ = vdom.rebuild();
+
+        let mut renderer = self.renderers.pull(pre_renderer);
+
+        let mut html = String::new();
+
+        let result = write!(
+            &mut html,
+            r#"
         <!DOCTYPE html>
         <html>
         <head>{head}
         </head><body>
         <div id="main">"#
-    );
+        );
 
-    if let Err(err) = result {
-        eprintln!("Failed to write to html: {}", err);
-    }
+        if let Err(err) = result {
+            eprintln!("Failed to write to html: {}", err);
+        }
 
-    let _ = renderer.render_to(&mut html, &vdom);
+        let _ = renderer.render_to(&mut html, &vdom);
 
-    if let Err(err) = write!(
-        &mut html,
-        r#"</div>
+        if let Err(err) = write!(
+            &mut html,
+            r#"</div>
         <script type="module">
         import init from "/{base_path}/assets/dioxus/{application_name}.js";
     init("/{base_path}/assets/dioxus/{application_name}_bg.wasm").then(wasm => {{
@@ -50,31 +92,11 @@ fn dioxus_ssr_html<P: 'static + Clone>(cfg: &ServeConfig<P>, renderer: &mut Rend
     </script>
     </body>
     </html>"#
-    ) {
-        eprintln!("Failed to write to html: {}", err);
-    }
-
-    html
-}
-
-#[derive(Clone)]
-pub struct SSRState {
-    // We keep a cache of renderers to avoid re-creating them on every request. They are boxed to make them very cheap to move
-    renderers: Arc<object_pool::Pool<Renderer>>,
-}
-
-impl Default for SSRState {
-    fn default() -> Self {
-        Self {
-            renderers: Arc::new(object_pool::Pool::new(10, pre_renderer)),
+        ) {
+            eprintln!("Failed to write to html: {}", err);
         }
-    }
-}
 
-impl SSRState {
-    pub fn render<P: 'static + Clone>(&self, cfg: &ServeConfig<P>) -> String {
-        let mut renderer = self.renderers.pull(pre_renderer);
-        dioxus_ssr_html(cfg, &mut renderer)
+        html
     }
 }