fix dioxus ssr

This commit is contained in:
Evan Almloff committed 2024-01-10 17:57:15 -06:00
1 parent dc58212508
commit 4a1a00b0f0
27 files changed
+143 -141

No files matched your search

+1
View File
@@ -31,6 +31,7 @@ argh = "0.1.4"
serde = "1.0.120"
serde_json = "1.0.61"
fs_extra = "1.2.0"
dioxus-signals.workspace = true
[features]
default = ["incremental"]
+8 -8
View File
@@ -18,7 +18,7 @@ This crate is a part of the broader Dioxus ecosystem. For more resources about D
Dioxus SSR provides utilities to render Dioxus components to valid HTML. Once rendered, the HTML can be rehydrated client-side or served from your web server of choice.
```rust, ignore
let app: Component = |cx| cx.render(rsx!(div {"hello world!"}));
let app: Component = |cx| render!(div {"hello world!"});
let mut vdom = VirtualDom::new(app);
let _ = vdom.rebuild();
@@ -29,12 +29,12 @@ assert_eq!(text, "<div>hello world!</div>")
## Basic Usage
The simplest example is to simply render some `rsx!` nodes to HTML. This can be done with the [`render_lazy`] API.
The simplest example is to simply render some `render!` nodes to HTML. This can be done with the [`render_element`] API.
```rust, ignore
let content = dioxus_ssr::render_lazy(rsx!{
let content = dioxus_ssr::render_element(render!{
div {
(0..5).map(|i| rsx!(
(0..5).map(|i| render!(
"Number: {i}"
))
}
@@ -84,19 +84,19 @@ The rest of the space - IE doing this more efficiently, caching the VirtualDom,
## 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 a `Renderer` and call `render_lazy`.
Dioxus SSR needs an arena to allocate from - whether it be the VirtualDom or a dedicated Bump allocator. To render `render!` directly to a string, you'll want to create a `Renderer` and call `render_element`.
```rust, ignore
let text = dioxus_ssr::Renderer::new().render_lazy(rsx!{
let text = dioxus_ssr::Renderer::new().render_element(render!{
div { "hello world" }
});
assert_eq!(text, "<div>hello world!</div>")
```
This can be automated with the `render_lazy!` macro:
This can be automated with the `render_element!` macro:
```rust, ignore
let text = render_lazy!(rsx!( div { "hello world" } ));
let text = render_element!(render!( div { "hello world" } ));
```
## Usage in static site generation
+2 -1
View File
@@ -14,6 +14,7 @@ pub mod eval;
pub mod renderer;
pub mod template;
use dioxus_core::NoOpMutations;
use dioxus_core::{Element, VirtualDom};
pub use crate::renderer::Renderer;
@@ -28,7 +29,7 @@ pub fn render_element(element: Element) -> String {
let mut dom = VirtualDom::new_with_props(lazy_app, element);
dom.in_runtime(crate::eval::init_eval);
_ = dom.rebuild(&mut NoOpMutations);
dom.rebuild(&mut NoOpMutations);
Renderer::new().render(&dom)
}
+10 -33
View File
@@ -1,5 +1,6 @@
use super::cache::Segment;
use crate::cache::StringCache;
use dioxus_core::RenderReturn;
use dioxus_core::Attribute;
use dioxus_core::{prelude::*, AttributeValue, DynamicNode};
@@ -118,8 +119,7 @@ impl Renderer {
if self.skip_components {
write!(buf, "<{}><{}/>", node.name, node.name)?;
} else {
let id = node.mounted_scope().unwrap();
let scope = dom.get_scope(id).unwrap();
let scope = node.mounted_scope(*idx, template, dom).unwrap();
let node = scope.root_node();
match node {
RenderReturn::Ready(node) => {
@@ -227,7 +227,7 @@ impl Renderer {
fn to_string_works() {
use dioxus::prelude::*;
fn app(cx: Scope) -> Element {
fn app(_: ()) -> Element {
let dynamic = 123;
let dyn2 = "</diiiiiiiiv>"; // this should be escaped
@@ -240,13 +240,13 @@ fn to_string_works() {
div {}
div { "nest 2" }
"{dyn2}"
(0..5).map(|i| rsx! { div { "finalize {i}" } })
(0..5).map(|i| render! { div { "finalize {i}" } })
}
}
}
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
let mut renderer = Renderer::new();
let out = renderer.render(&dom);
@@ -285,7 +285,7 @@ fn to_string_works() {
fn empty_for_loop_works() {
use dioxus::prelude::*;
fn app(cx: Scope) -> Element {
fn app(_: ()) -> Element {
render! {
div { class: "asdasdasd",
for _ in (0..5) {
@@ -296,7 +296,7 @@ fn empty_for_loop_works() {
}
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
let mut renderer = Renderer::new();
let out = renderer.render(&dom);
@@ -328,35 +328,12 @@ fn empty_for_loop_works() {
fn empty_render_works() {
use dioxus::prelude::*;
fn app(cx: Scope) -> Element {
fn app(_: ()) -> Element {
render! {}
}
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
let mut renderer = Renderer::new();
let out = renderer.render(&dom);
for item in renderer.template_cache.iter() {
if item.1.segments.len() > 5 {
assert_eq!(item.1.segments, vec![]);
}
}
assert_eq!(out, "");
}
#[test]
fn empty_rsx_works() {
use dioxus::prelude::*;
fn app(_: Scope) -> Element {
rsx! {};
None
}
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
let mut renderer = Renderer::new();
let out = renderer.render(&dom);
@@ -415,7 +392,7 @@ pub(crate) fn truthy(value: &AttributeValue) -> bool {
pub(crate) fn write_attribute(buf: &mut impl Write, attr: &Attribute) -> std::fmt::Result {
let name = &attr.name;
match attr.value {
match &attr.value {
AttributeValue::Text(value) => write!(buf, " {name}=\"{value}\""),
AttributeValue::Bool(value) => write!(buf, " {name}={value}"),
AttributeValue::Int(value) => write!(buf, " {name}={value}"),
+4 -4
View File
@@ -2,7 +2,7 @@ use dioxus::prelude::*;
#[test]
fn static_boolean_attributs() {
fn app(cx: Scope) -> Element {
fn app(_: ()) -> Element {
render! {
div { hidden: "false" }
div { hidden: "true" }
@@ -10,7 +10,7 @@ fn static_boolean_attributs() {
}
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert_eq!(
dioxus_ssr::render(&dom),
@@ -20,7 +20,7 @@ fn static_boolean_attributs() {
#[test]
fn dynamic_boolean_attributs() {
fn app(cx: Scope) -> Element {
fn app(_: ()) -> Element {
render! {
div { hidden: false }
div { hidden: true }
@@ -28,7 +28,7 @@ fn dynamic_boolean_attributs() {
}
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert_eq!(
dioxus_ssr::render(&dom),
+31 -29
View File
@@ -2,12 +2,12 @@ use dioxus::prelude::*;
#[test]
fn root_ids() {
fn app(cx: Scope) -> Element {
fn app(_: ()) -> Element {
render! { div { width: "100px" } }
}
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert_eq!(
dioxus_ssr::pre_render(&dom),
@@ -17,7 +17,7 @@ fn root_ids() {
#[test]
fn dynamic_attributes() {
fn app(cx: Scope) -> Element {
fn app(_: ()) -> Element {
let dynamic = 123;
render! {
div { width: "100px", div { width: "{dynamic}px" } }
@@ -25,7 +25,7 @@ fn dynamic_attributes() {
}
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert_eq!(
dioxus_ssr::pre_render(&dom),
@@ -35,21 +35,21 @@ fn dynamic_attributes() {
#[test]
fn listeners() {
fn app(cx: Scope) -> Element {
fn app(_: ()) -> Element {
render! {
div { width: "100px", div { onclick: |_| {} } }
}
}
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert_eq!(
dioxus_ssr::pre_render(&dom),
r#"<div style="width:100px;" data-node-hydration="0"><div data-node-hydration="1,click:1"></div></div>"#
);
fn app2(cx: Scope) -> Element {
fn app2(_: ()) -> Element {
let dynamic = 123;
render! {
div { width: "100px", div { width: "{dynamic}px", onclick: |_| {} } }
@@ -57,7 +57,7 @@ fn listeners() {
}
let mut dom = VirtualDom::new(app2);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert_eq!(
dioxus_ssr::pre_render(&dom),
@@ -67,7 +67,7 @@ fn listeners() {
#[test]
fn text_nodes() {
fn app(cx: Scope) -> Element {
fn app(_: ()) -> Element {
let dynamic_text = "hello";
render! {
div { dynamic_text }
@@ -75,14 +75,14 @@ fn text_nodes() {
}
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert_eq!(
dioxus_ssr::pre_render(&dom),
r#"<div data-node-hydration="0"><!--node-id1-->hello<!--#--></div>"#
);
fn app2(cx: Scope) -> Element {
fn app2(_: ()) -> Element {
let dynamic = 123;
render! {
div { "{dynamic}", "{1234}" }
@@ -90,7 +90,7 @@ fn text_nodes() {
}
let mut dom = VirtualDom::new(app2);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert_eq!(
dioxus_ssr::pre_render(&dom),
@@ -101,27 +101,27 @@ fn text_nodes() {
#[allow(non_snake_case)]
#[test]
fn components_hydrate() {
fn app(cx: Scope) -> Element {
fn app(_: ()) -> Element {
render! { Child {} }
}
fn Child(cx: Scope) -> Element {
fn Child(_: ()) -> Element {
render! { div { "hello" } }
}
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert_eq!(
dioxus_ssr::pre_render(&dom),
r#"<div data-node-hydration="0">hello</div>"#
);
fn app2(cx: Scope) -> Element {
fn app2(_: ()) -> Element {
render! { Child2 {} }
}
fn Child2(cx: Scope) -> Element {
fn Child2(_: ()) -> Element {
let dyn_text = "hello";
render! {
div { dyn_text }
@@ -129,34 +129,34 @@ fn components_hydrate() {
}
let mut dom = VirtualDom::new(app2);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert_eq!(
dioxus_ssr::pre_render(&dom),
r#"<div data-node-hydration="0"><!--node-id1-->hello<!--#--></div>"#
);
fn app3(cx: Scope) -> Element {
fn app3(_: ()) -> Element {
render! { Child3 {} }
}
fn Child3(cx: Scope) -> Element {
fn Child3(_: ()) -> Element {
render! { div { width: "{1}" } }
}
let mut dom = VirtualDom::new(app3);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert_eq!(
dioxus_ssr::pre_render(&dom),
r#"<div style="width:1;" data-node-hydration="0"></div>"#
);
fn app4(cx: Scope) -> Element {
fn app4(_: ()) -> Element {
render! { Child4 {} }
}
fn Child4(cx: Scope) -> Element {
fn Child4(_: ()) -> Element {
render! {
for _ in 0..2 {
render! {
@@ -169,7 +169,7 @@ fn components_hydrate() {
}
let mut dom = VirtualDom::new(app4);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert_eq!(
dioxus_ssr::pre_render(&dom),
@@ -179,18 +179,20 @@ fn components_hydrate() {
#[test]
fn hello_world_hydrates() {
fn app(cx: Scope) -> Element {
let mut count = use_state(cx, || 0);
use dioxus_signals::use_signal;
cx.render(rsx! {
fn app(_: ()) -> Element {
let mut count = use_signal(|| 0);
render! {
h1 { "High-Five counter: {count}" }
button { onclick: move |_| count += 1, "Up high!" }
button { onclick: move |_| count -= 1, "Down low!" }
})
}
}
let mut dom = VirtualDom::new(app);
_ = dbg!(dom.rebuild());
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert_eq!(
dioxus_ssr::pre_render(&dom),
+4 -4
View File
@@ -2,25 +2,25 @@ use dioxus::prelude::*;
#[test]
fn static_inner_html() {
fn app(cx: Scope) -> Element {
fn app(_: ()) -> Element {
render! { div { dangerous_inner_html: "<div>1234</div>" } }
}
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert_eq!(dioxus_ssr::render(&dom), r#"<div><div>1234</div></div>"#);
}
#[test]
fn dynamic_inner_html() {
fn app(cx: Scope) -> Element {
fn app(_: ()) -> Element {
let inner_html = "<div>1234</div>";
render! { div { dangerous_inner_html: "{inner_html}" } }
}
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert_eq!(dioxus_ssr::render(&dom), r#"<div><div>1234</div></div>"#);
}
+16 -13
View File
@@ -2,18 +2,17 @@ use dioxus::prelude::*;
#[test]
fn simple() {
#[component]
fn App(cx: Scope) -> Element {
fn App(_: ()) -> Element {
render! { div { "hello!" } }
}
let mut dom = VirtualDom::new(App);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert_eq!(dioxus_ssr::render(&dom), "<div>hello!</div>");
assert_eq!(
dioxus_ssr::render_lazy(rsx!( div {"hello!"} )),
dioxus_ssr::render_element(render!( div {"hello!"} )),
"<div>hello!</div>"
);
}
@@ -21,9 +20,9 @@ fn simple() {
#[test]
fn lists() {
assert_eq!(
dioxus_ssr::render_lazy(rsx! {
dioxus_ssr::render_element(render! {
ul {
(0..5).map(|i| rsx! {
(0..5).map(|i| render! {
li { "item {i}" }
})
}
@@ -36,7 +35,7 @@ fn lists() {
fn dynamic() {
let dynamic = 123;
assert_eq!(
dioxus_ssr::render_lazy(rsx! {
dioxus_ssr::render_element(render! {
div { "Hello world 1 -->" "{dynamic}" "<-- Hello world 2" }
}),
"<div>Hello world 1 --&gt;123&lt;-- Hello world 2</div>"
@@ -45,15 +44,19 @@ fn dynamic() {
#[test]
fn components() {
#[component]
fn MyComponent(cx: Scope, name: i32) -> Element {
#[derive(Props, Clone, PartialEq)]
struct MyComponentProps {
name: i32,
}
fn MyComponent(MyComponentProps { name }: MyComponentProps) -> Element {
render! { div { "component {name}" } }
}
assert_eq!(
dioxus_ssr::render_lazy(rsx! {
dioxus_ssr::render_element(render! {
div {
(0..5).map(|name| rsx! {
(0..5).map(|name| render! {
MyComponent { name: name }
})
}
@@ -65,9 +68,9 @@ fn components() {
#[test]
fn fragments() {
assert_eq!(
dioxus_ssr::render_lazy(rsx! {
dioxus_ssr::render_element(render! {
div {
(0..5).map(|_| rsx! (()))
(0..5).map(|_| render! (()))
}
}),
"<div></div>"
+4 -4
View File
@@ -2,12 +2,12 @@ use dioxus::prelude::*;
#[test]
fn static_styles() {
fn app(cx: Scope) -> Element {
fn app(_: ()) -> Element {
render! { div { width: "100px" } }
}
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert_eq!(
dioxus_ssr::render(&dom),
@@ -20,7 +20,7 @@ fn partially_dynamic_styles() {
let dynamic = 123;
assert_eq!(
dioxus_ssr::render_lazy(rsx! {
dioxus_ssr::render_element(render! {
div { width: "100px", height: "{dynamic}px" }
}),
r#"<div style="width:100px;height:123px;"></div>"#
@@ -32,7 +32,7 @@ fn dynamic_styles() {
let dynamic = 123;
assert_eq!(
dioxus_ssr::render_lazy(rsx! {
dioxus_ssr::render_element(render! {
div { width: "{dynamic}px" }
}),
r#"<div style="width:123px;"></div>"#