Subtree memorization / reactive templates (#488)
This commit adds subtree memoization to Dioxus. Subtree memoization is basically a compile-time step that drastically reduces the amount of work the diffing engine needs to do at runtime by extracting non-changing nodes out into a static "template." Templates are then understood by the various renderers in the ecosystem as a faster way of rendering the same items. For example, in the web, templates are simply a set of DOM Nodes created once and then cloned later. This is the same pattern frameworks like Lithtml and SolidJS use to achieve near-perfect performance. Subtree memoization adds an additional level of complexity to Dioxus. The RSX macro needs to be much smarter to identify changing/nonchanging nodes and generate a mapping between the Template and its runtime counterparts. This commit represents a working starter point for this work, adding support for templates for the web, desktop, liveview, ssr, and native-core renderers. In the future we will try to shrink code generation, generally improve performance, and simplify our implementation.
This commit is contained in:
1 parent
b32fd2d2cd
commit
047ed1e553
80 files changed
+6774
-2552
No files matched your search
+12
-17
@@ -10,10 +10,10 @@ use syn::{
|
||||
// =======================================
|
||||
// Parse the VNode::Element type
|
||||
// =======================================
|
||||
#[derive(PartialEq, Eq)]
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
|
||||
pub struct Element {
|
||||
pub name: Ident,
|
||||
pub key: Option<LitStr>,
|
||||
pub key: Option<IfmtInput>,
|
||||
pub attributes: Vec<ElementAttrNamed>,
|
||||
pub children: Vec<BodyNode>,
|
||||
pub _is_static: bool,
|
||||
@@ -46,7 +46,7 @@ impl Parse for Element {
|
||||
content.parse::<Token![:]>()?;
|
||||
|
||||
if content.peek(LitStr) && content.peek2(Token![,]) {
|
||||
let value = content.parse::<LitStr>()?;
|
||||
let value = content.parse()?;
|
||||
attributes.push(ElementAttrNamed {
|
||||
el_name: el_name.clone(),
|
||||
attr: ElementAttr::CustomAttrText { name, value },
|
||||
@@ -164,7 +164,7 @@ impl ToTokens for Element {
|
||||
let children = &self.children;
|
||||
|
||||
let key = match &self.key {
|
||||
Some(ty) => quote! { Some(format_args_f!(#ty)) },
|
||||
Some(ty) => quote! { Some(#ty) },
|
||||
None => quote! { None },
|
||||
};
|
||||
|
||||
@@ -190,16 +190,16 @@ impl ToTokens for Element {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
|
||||
pub enum ElementAttr {
|
||||
/// attribute: "valuee {}"
|
||||
AttrText { name: Ident, value: LitStr },
|
||||
AttrText { name: Ident, value: IfmtInput },
|
||||
|
||||
/// attribute: true,
|
||||
AttrExpression { name: Ident, value: Expr },
|
||||
|
||||
/// "attribute": "value {}"
|
||||
CustomAttrText { name: LitStr, value: LitStr },
|
||||
CustomAttrText { name: LitStr, value: IfmtInput },
|
||||
|
||||
/// "attribute": true,
|
||||
CustomAttrExpression { name: LitStr, value: Expr },
|
||||
@@ -231,7 +231,7 @@ impl ElementAttr {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Hash)]
|
||||
pub struct ElementAttrNamed {
|
||||
pub el_name: Ident,
|
||||
pub attr: ElementAttr,
|
||||
@@ -244,29 +244,24 @@ impl ToTokens for ElementAttrNamed {
|
||||
tokens.append_all(match attr {
|
||||
ElementAttr::AttrText { name, value } => {
|
||||
quote! {
|
||||
dioxus_elements::#el_name.#name(__cx, format_args_f!(#value))
|
||||
__cx.attr_disciption( dioxus_elements::#el_name::#name, #value)
|
||||
}
|
||||
}
|
||||
ElementAttr::AttrExpression { name, value } => {
|
||||
quote! {
|
||||
dioxus_elements::#el_name.#name(__cx, #value)
|
||||
__cx.attr_disciption( dioxus_elements::#el_name::#name, #value)
|
||||
}
|
||||
}
|
||||
ElementAttr::CustomAttrText { name, value } => {
|
||||
quote! {
|
||||
__cx.attr( #name, format_args_f!(#value), None, false )
|
||||
__cx.attr( #name, #value, None, false )
|
||||
}
|
||||
}
|
||||
ElementAttr::CustomAttrExpression { name, value } => {
|
||||
quote! {
|
||||
__cx.attr( #name, format_args_f!(#value), None, false )
|
||||
__cx.attr( #name, #value, None, false )
|
||||
}
|
||||
}
|
||||
// ElementAttr::EventClosure { name, closure } => {
|
||||
// quote! {
|
||||
// dioxus_elements::on::#name(__cx, #closure)
|
||||
// }
|
||||
// }
|
||||
ElementAttr::EventTokens { name, tokens } => {
|
||||
quote! {
|
||||
dioxus_elements::on::#name(__cx, #tokens)
|
||||
|
||||
Reference in new issue
Block a user