dioxus/packages/core
Jonathan Kelley f4fb5bb454 feat: integrate serialization and string borrowing
This commit adds lifetimes to the diff and realdom methods so consumers may borrow the contents of the DOM for serialization or asynchronous modifications.
2021-06-28 12:05:17 -04:00
..
.vscode feat: events work again! 2021-06-23 01:44:48 -04:00
examples feat: integrate serialization and string borrowing 2021-06-28 12:05:17 -04:00
src feat: integrate serialization and string borrowing 2021-06-28 12:05:17 -04:00
tests Feat: ensure mutabality is okay when not double-using the components 2021-03-12 16:58:30 -05:00
architecture.md wip: moving to imperative method of dom 2021-06-20 01:52:32 -04:00
Cargo.toml wip: stack-based "real child iterator" 2021-06-26 03:06:29 -04:00
README.md docs: add some more sources in the core implementation 2021-06-21 01:35:12 -04:00

Dioxus-core

This is the core crate for the Dioxus Virtual DOM. This README will focus on the technical design and layout of this Virtual DOM implementation. If you want to read more about using Dioxus, then check out the Dioxus crate, documentation, and website.

We reserve the "dioxus" name and aggregate all the various renderers under it. If you want just a single dioxus renderer, then chose from "dioxus-web", "dioxus-desktop", etc.

Internals

Dioxus-core builds off the many frameworks that came before it. Notably, Dioxus borrows these concepts:

  • React: hooks, concurrency, suspense
  • Dodrio: bump allocation, double buffering, and source code for NodeBuilder
  • Percy: html! macro architecture, platform-agnostic edits
  • Yew: passion and inspiration ❤️
  • InfernoJS: approach to fragments and node diffing
  • Preact: approach for normalization and ref

Dioxus-core leverages some really cool techniques and hits a very high level of parity with mature frameworks. Some unique features include:

  • managed lifetimes for borrowed data
  • suspended nodes (task/fiber endpoints) for asynchronous vnodes
  • custom memory allocator for vnodes and all text content
  • support for fragments w/ lazy normalization

There's certainly more to the story, but these optimizations make Dioxus memory use and allocation count extremely minimal. For an average application, it is likely that zero allocations will need to be performed once the app has been mounted. Only when new components are added to the dom will allocations occur - and only en mass. The space of old VNodes is dynamically recycled as new nodes are added. Additionally, Dioxus tracks the average memory footprint of previous components to estimate how much memory allocate for future components.

All in all, Dioxus treats memory as an incredibly valuable resource. Combined with the memory-efficient footprint of WASM compilation, Dioxus apps can scale to thousands of components and still stay snappy and respect your RAM usage.

Goals

We have big goals for Dioxus. The final implementation must:

  • Be fast. Allocators are typically slow in WASM/Rust, so we should have a smart way of allocating.
  • Be extremely memory efficient. Servers should handle tens of thousands of simultaneous VDoms with no problem.
  • Be concurrent. Components should be able to pause rendering using a threading mechanism.
  • Be "remote". Edit lists should be separate from the Renderer implementation.
  • Support SSR. VNodes should render to a string that can be served via a web server.
  • Be "live". Components should be able to be both server rendered and client rendered without needing frontend APIs.
  • Be modular. Components and hooks should be work anywhere without worrying about target platform.

Optimizations

  • Support a pluggable allocation strategy that makes VNode creation very fast
  • Support lazy VNodes (ie VNodes that are not actually created when the html! macro is used)
  • Support advanced diffing strategies (patience, Meyers, etc)

rsx!{ "this is a text node" }

rsx!{
    div {}
    "asd"
    div {}
    div {}
}
rsx!{
    div {
        a {}
        b {}
        c {}
        Container {
            Container {
                Container {
                    Container {
                        Container {
                            div {}
                        }
                    }
                }
            }
        }
    }
}