ソースを参照

feat: add more to ssr renderer

Jonathan Kelley 3 年 前
コミット
63568c5
3 ファイル変更80 行追加9 行削除
  1. 0 3
      packages/ssr/.vscode/settings.json
  2. 19 2
      packages/ssr/README.md
  3. 61 4
      packages/ssr/src/lib.rs

+ 0 - 3
packages/ssr/.vscode/settings.json

@@ -1,3 +0,0 @@
-{
-    "rust-analyzer.inlayHints.enable": false
-}

+ 19 - 2
packages/ssr/README.md

@@ -14,7 +14,7 @@ let mut vdom = VirtualDOM::new(App);
 let _ = vdom.rebuild();
 
 // Render the entire virtualdom from the root
-let text = dioxus_ssr::render_vdom(&vdom, |c| c);
+let text = dioxus::ssr::render_vdom(&vdom, |c| c);
 assert_eq!(text, "<div>hello world!</div>")
 ```
 
@@ -40,12 +40,29 @@ let text = dioxus::ssr::render_vdom(App, |cfg| cfg.pre_render(true));
 Dioxus SSR can also be to render on the server. Obviously, you can just render the VirtualDOM to a string and send that down.
 
 ```rust
-let text = dioxus_ssr::render_vdom(&vdom, |c| c);
+let text = dioxus::ssr::render_vdom(&vdom, |c| c);
 assert_eq!(text, "<div>hello world!</div>")
 ```
 
 The rest of the space - IE doing this more efficiently, caching the virtualdom, etc, will all need to be a custom implementation for now.
 
+## Usage without a VirtualDom
+
+Dioxus SSR needs an arena to allocate from - whether it be the VirtualDom or a dedicated Bump allocator. To render `rsx!` directly to a string, you'll want to create an `SsrRenderer` and call `render_lazy`.
+
+```rust
+let text = dioxus::ssr::SsrRenderer::new().render_lazy(rsx!{
+    div { "hello world" }
+});
+assert_eq!(text, "<div>hello world!</div>")
+```
+
+This can be automated with the `render_lazy!` macro:
+
+```rust
+let text = render_lazy!(rsx!( div { "hello world" } ));
+```
+
 ## Usage in static site generation
 
 Dioxus SSR is a powerful tool to generate static sites. Using Dioxus for static site generation _is_ a bit overkill, however. The new documentation generation library, Doxie, is essentially Dioxus SSR on steroids designed for static site generation with client-side hydration.

+ 61 - 4
packages/ssr/src/lib.rs

@@ -12,8 +12,49 @@
 
 use std::fmt::{Display, Formatter};
 
+use dioxus_core::exports::bumpalo;
+use dioxus_core::nodes::IntoVNode;
 use dioxus_core::*;
 
+macro_rules! render_lazy {
+    ($f:expr) => {
+        $crate::SsrRenderer::new().render_lazy($f)
+    };
+}
+
+pub struct SsrRenderer {
+    inner: bumpalo::Bump,
+}
+impl Default for SsrRenderer {
+    fn default() -> Self {
+        Self {
+            inner: bumpalo::Bump::new(),
+        }
+    }
+}
+
+impl SsrRenderer {
+    pub fn new() -> Self {
+        SsrRenderer::default()
+    }
+
+    pub fn render_lazy<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>>(
+        &'a self,
+        f: LazyNodes<'a, F>,
+    ) -> String {
+        let factory = NodeFactory::new(&self.inner);
+        let root = f.into_vnode(factory);
+        format!(
+            "{:}",
+            TextRenderer {
+                cfg: SsrConfig::default(),
+                root: &root,
+                vdom: None
+            }
+        )
+    }
+}
+
 pub fn render_vnode(vnode: &VNode, string: &mut String) {}
 
 pub fn render_vdom(dom: &VirtualDom, cfg: impl FnOnce(SsrConfig) -> SsrConfig) -> String {
@@ -52,19 +93,19 @@ pub fn render_vdom_scope(vdom: &VirtualDom, scope: ScopeId) -> Option<String> {
 /// let output = format!("{}", renderer);
 /// assert_eq!(output, "<div>hello world</div>");
 /// ```
-pub struct TextRenderer<'a> {
+pub struct TextRenderer<'a, 'b> {
     vdom: Option<&'a VirtualDom>,
-    root: &'a VNode<'a>,
+    root: &'b VNode<'a>,
     cfg: SsrConfig,
 }
 
-impl Display for TextRenderer<'_> {
+impl Display for TextRenderer<'_, '_> {
     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
         self.html_render(self.root, f, 0)
     }
 }
 
-impl<'a> TextRenderer<'a> {
+impl<'a> TextRenderer<'a, '_> {
     pub fn from_vdom(vdom: &'a VirtualDom, cfg: SsrConfig) -> Self {
         Self {
             cfg,
@@ -341,4 +382,20 @@ mod tests {
         dom.rebuild();
         dbg!(render_vdom(&dom, |c| c));
     }
+
+    #[test]
+    fn lazy() {
+        let p1 = SsrRenderer::new().render_lazy(rsx! {
+            div {
+                "ello"
+            }
+        });
+
+        let p2 = render_lazy!(rsx! {
+            div {
+                "ello"
+            }
+        });
+        assert_eq!(p1, p2);
+    }
 }