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
@@ -1,6 +1,5 @@
|
||||
use crate::{GlobalAttributes, SvgAttributes};
|
||||
use dioxus_core::*;
|
||||
use std::fmt::Arguments;
|
||||
|
||||
macro_rules! builder_constructors {
|
||||
(
|
||||
@@ -28,10 +27,12 @@ macro_rules! builder_constructors {
|
||||
|
||||
impl $name {
|
||||
$(
|
||||
$(#[$attr_method])*
|
||||
pub fn $fil<'a>(&self, cx: NodeFactory<'a>, val: Arguments) -> Attribute<'a> {
|
||||
cx.attr(stringify!($fil), val, None, false)
|
||||
}
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const $fil: AttributeDiscription = AttributeDiscription{
|
||||
name: stringify!($fil),
|
||||
namespace: None,
|
||||
volatile: false
|
||||
};
|
||||
)*
|
||||
}
|
||||
)*
|
||||
@@ -57,9 +58,13 @@ macro_rules! builder_constructors {
|
||||
|
||||
impl $name {
|
||||
$(
|
||||
pub fn $fil<'a>(&self, cx: NodeFactory<'a>, val: Arguments) -> Attribute<'a> {
|
||||
cx.attr(stringify!($fil), val, Some(stringify!($namespace)), false)
|
||||
}
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const $fil: AttributeDiscription = AttributeDiscription{
|
||||
name: stringify!($fil),
|
||||
namespace: Some(stringify!($namespace)),
|
||||
volatile: false
|
||||
};
|
||||
)*
|
||||
}
|
||||
)*
|
||||
@@ -1061,13 +1066,19 @@ impl input {
|
||||
/// - `time`
|
||||
/// - `url`
|
||||
/// - `week`
|
||||
pub fn r#type<'a>(&self, cx: NodeFactory<'a>, val: Arguments) -> Attribute<'a> {
|
||||
cx.attr("type", val, None, false)
|
||||
}
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const r#type: AttributeDiscription = AttributeDiscription {
|
||||
name: "type",
|
||||
namespace: None,
|
||||
volatile: false,
|
||||
};
|
||||
|
||||
pub fn value<'a>(&self, cx: NodeFactory<'a>, val: Arguments) -> Attribute<'a> {
|
||||
cx.attr("value", val, None, true)
|
||||
}
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const value: AttributeDiscription = AttributeDiscription {
|
||||
name: "value",
|
||||
namespace: None,
|
||||
volatile: true,
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1077,41 +1088,63 @@ volatile attributes
|
||||
impl script {
|
||||
// r#async: Bool,
|
||||
// r#type: String, // TODO could be an enum
|
||||
pub fn r#type<'a>(&self, cx: NodeFactory<'a>, val: Arguments) -> Attribute<'a> {
|
||||
cx.attr("type", val, None, false)
|
||||
}
|
||||
pub fn r#script<'a>(&self, cx: NodeFactory<'a>, val: Arguments) -> Attribute<'a> {
|
||||
cx.attr("script", val, None, false)
|
||||
}
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const r#type: AttributeDiscription = AttributeDiscription {
|
||||
name: "type",
|
||||
namespace: None,
|
||||
volatile: false,
|
||||
};
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const r#script: AttributeDiscription = AttributeDiscription {
|
||||
name: "script",
|
||||
namespace: None,
|
||||
volatile: false,
|
||||
};
|
||||
}
|
||||
|
||||
impl button {
|
||||
pub fn r#type<'a>(&self, cx: NodeFactory<'a>, val: Arguments) -> Attribute<'a> {
|
||||
cx.attr("type", val, None, false)
|
||||
}
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const r#type: AttributeDiscription = AttributeDiscription {
|
||||
name: "type",
|
||||
namespace: None,
|
||||
volatile: false,
|
||||
};
|
||||
}
|
||||
|
||||
impl select {
|
||||
pub fn value<'a>(&self, cx: NodeFactory<'a>, val: Arguments) -> Attribute<'a> {
|
||||
cx.attr("value", val, None, true)
|
||||
}
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const value: AttributeDiscription = AttributeDiscription {
|
||||
name: "value",
|
||||
namespace: None,
|
||||
volatile: true,
|
||||
};
|
||||
}
|
||||
|
||||
impl option {
|
||||
pub fn selected<'a>(&self, cx: NodeFactory<'a>, val: Arguments) -> Attribute<'a> {
|
||||
cx.attr("selected", val, None, true)
|
||||
}
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const selected: AttributeDiscription = AttributeDiscription {
|
||||
name: "selected",
|
||||
namespace: None,
|
||||
volatile: true,
|
||||
};
|
||||
}
|
||||
|
||||
impl textarea {
|
||||
pub fn value<'a>(&self, cx: NodeFactory<'a>, val: Arguments) -> Attribute<'a> {
|
||||
cx.attr("value", val, None, true)
|
||||
}
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const value: AttributeDiscription = AttributeDiscription {
|
||||
name: "value",
|
||||
namespace: None,
|
||||
volatile: true,
|
||||
};
|
||||
}
|
||||
impl label {
|
||||
pub fn r#for<'a>(&self, cx: NodeFactory<'a>, val: Arguments) -> Attribute<'a> {
|
||||
cx.attr("for", val, None, false)
|
||||
}
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const r#for: AttributeDiscription = AttributeDiscription {
|
||||
name: "for",
|
||||
namespace: None,
|
||||
volatile: false,
|
||||
};
|
||||
}
|
||||
|
||||
builder_constructors! {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use dioxus_core::*;
|
||||
use std::fmt::Arguments;
|
||||
|
||||
macro_rules! no_namespace_trait_methods {
|
||||
(
|
||||
@@ -9,10 +8,12 @@ macro_rules! no_namespace_trait_methods {
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
$(#[$attr])*
|
||||
fn $name<'a>(&self, cx: NodeFactory<'a>, val: Arguments) -> Attribute<'a> {
|
||||
cx.attr(stringify!($name), val, None, false)
|
||||
}
|
||||
#[allow(non_upper_case_globals)]
|
||||
const $name: AttributeDiscription = AttributeDiscription{
|
||||
name: stringify!($name),
|
||||
namespace: None,
|
||||
volatile: false
|
||||
};
|
||||
)*
|
||||
};
|
||||
}
|
||||
@@ -24,11 +25,12 @@ macro_rules! style_trait_methods {
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
#[inline]
|
||||
$(#[$attr])*
|
||||
fn $name<'a>(&self, cx: NodeFactory<'a>, val: Arguments) -> Attribute<'a> {
|
||||
cx.attr($lit, val, Some("style"), false)
|
||||
}
|
||||
#[allow(non_upper_case_globals)]
|
||||
const $name: AttributeDiscription = AttributeDiscription{
|
||||
name: $lit,
|
||||
namespace: Some("style"),
|
||||
volatile: false
|
||||
};
|
||||
)*
|
||||
};
|
||||
}
|
||||
@@ -40,10 +42,12 @@ macro_rules! aria_trait_methods {
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
$(#[$attr])*
|
||||
fn $name<'a>(&self, cx: NodeFactory<'a>, val: Arguments) -> Attribute<'a> {
|
||||
cx.attr($lit, val, None, false)
|
||||
}
|
||||
#[allow(non_upper_case_globals)]
|
||||
const $name: AttributeDiscription = AttributeDiscription{
|
||||
name: $lit,
|
||||
namespace: None,
|
||||
volatile: false
|
||||
};
|
||||
)*
|
||||
};
|
||||
}
|
||||
@@ -53,9 +57,12 @@ pub trait GlobalAttributes {
|
||||
///
|
||||
/// For more information, see the MDN docs:
|
||||
/// <https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault>
|
||||
fn prevent_default<'a>(&self, cx: NodeFactory<'a>, val: Arguments) -> Attribute<'a> {
|
||||
cx.attr("dioxus-prevent-default", val, None, false)
|
||||
}
|
||||
#[allow(non_upper_case_globals)]
|
||||
const prevent_default: AttributeDiscription = AttributeDiscription {
|
||||
name: "dioxus-prevent-default",
|
||||
namespace: None,
|
||||
volatile: false,
|
||||
};
|
||||
|
||||
no_namespace_trait_methods! {
|
||||
accesskey;
|
||||
@@ -597,9 +604,12 @@ pub trait SvgAttributes {
|
||||
///
|
||||
/// For more information, see the MDN docs:
|
||||
/// <https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault>
|
||||
fn prevent_default<'a>(&self, cx: NodeFactory<'a>, val: Arguments) -> Attribute<'a> {
|
||||
cx.attr("dioxus-prevent-default", val, None, false)
|
||||
}
|
||||
#[allow(non_upper_case_globals)]
|
||||
const prevent_default: AttributeDiscription = AttributeDiscription {
|
||||
name: "dioxus-prevent-default",
|
||||
namespace: None,
|
||||
volatile: false,
|
||||
};
|
||||
aria_trait_methods! {
|
||||
accent_height: "accent-height",
|
||||
accumulate: "accumulate",
|
||||
|
||||
Reference in new issue
Block a user