From 63568c546c76375aa8acb0b8d2555727ef48edc4 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Mon, 18 Oct 2021 12:53:56 -0400 Subject: [PATCH] feat: add more to ssr renderer --- packages/ssr/.vscode/settings.json | 3 -- packages/ssr/README.md | 21 +++++++++- packages/ssr/src/lib.rs | 65 ++++++++++++++++++++++++++++-- 3 files changed, 80 insertions(+), 9 deletions(-) delete mode 100644 packages/ssr/.vscode/settings.json diff --git a/packages/ssr/.vscode/settings.json b/packages/ssr/.vscode/settings.json deleted file mode 100644 index 80f51cff8..000000000 --- a/packages/ssr/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "rust-analyzer.inlayHints.enable": false -} \ No newline at end of file diff --git a/packages/ssr/README.md b/packages/ssr/README.md index 47ca4ebcd..7efb5ca92 100644 --- a/packages/ssr/README.md +++ b/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, "
hello world!
") ``` @@ -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, "
hello world!
") ``` 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, "
hello world!
") +``` + +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. diff --git a/packages/ssr/src/lib.rs b/packages/ssr/src/lib.rs index 96a84f161..fa87679c1 100644 --- a/packages/ssr/src/lib.rs +++ b/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 { /// let output = format!("{}", renderer); /// assert_eq!(output, "
hello world
"); /// ``` -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); + } }