rustwasm / team

A point of coordination for all things Rust and WebAssembly
MIT License
1.44k stars 60 forks source link

CSS in Rust + Reactive streams #243

Open Pauan opened 5 years ago

Pauan commented 5 years ago

I saw that the Rust+Wasm WG notes mentions CSS in Rust and Reactive streams.

I would like to point out that I have spent the past several months working on this, and I have already created robust, full featured, and fast solutions: futures-signals and dominator.

They are currently missing documentation, mostly because it was blocked on https://github.com/rust-lang/rust/issues/50159. With that fixed, I plan to get them into good shape. In the meantime, I'm happy to answer questions and offer advice.

Even though they're missing docs, the actual functionality is very solid: I've used them both in multiple mediumish (10,000+ LoC) projects, and they've worked out fantastic. I haven't run any benchmarks, but the performance seems very good as well.


futures-signals has extensive APIs for reactive streams of values.

It's based upon several years of research I've done on FRP systems, and built on top of the wonderful Futures API.

It is designed to be completely target agnostic: it can work in any environment that supports Futures, including the server, desktop, wasm, embedded devices, etc.

It's also designed to work with many use cases, it can be used for pretty much anything: server processing, databases, multiple different DOM libraries, audio, etc.

It is designed to be zero-cost, just like the Futures API itself. Almost everything is stack allocated. I haven't run benchmarks yet, but performance should be very good.

It fully supports conversion to/from Futures and Streams, and it also fully supports pinned Futures (so it works with async/await!).

Right now the best way to learn about it is to read the tutorial (or ask me questions).

The tutorial is really hard to read right now, but after https://github.com/rust-lang/rust/issues/50159 rolls into Stable you will be able to read the tutorial on docs.rs (with nice Markdown formatting).


dominator is a full featured zero-cost DOM library.

Unlike most other libraries, it does not create virtual DOM at all, everything is real DOM nodes. That also means it does not do any DOM diffing (so it is much faster).

It heavily avoids heap allocation, so in many situations it is fully stack allocated, and even when it needs heap allocation it does the minimum allocation necessary.

It can be used without futures-signals to create static (un-changing) DOM.

Or if you want to have dynamic DOM which can change over time, it has extensive support for using it together with futures-signals.

When the Signal or SignalVec changes, it will automatically and efficiently update the DOM, ensuring that the DOM always stays in sync with your application's state.

It does not do DOM diffing, and the changes are zero-cost and constant time: it only updates the minimum that is needed.

It has very good built-in support for animations (which are very efficient), which is something that most virtual DOM libraries struggle with.

Even though it's using raw DOM nodes (not virtual DOM), the API is declarative, just like virtual DOM, so you get the benefits of virtual DOM without the performance and interop drawbacks.

In addition to having full support for all HTML (and SVG) elements, properties, and attributes, it also has support for "CSS in Rust":

lazy_static! {
    static ref MY_CUSTOM_CLASS: String = class! {
        .style("display", "flex")
        .style("flex-direction", "row")
        .style("align-items", "center")
    };
}

This dynamically creates a <style> element, so it is very efficient, and it even supports Signals (so you can efficiently change a class's style, which updates multiple elements at once).

Every time you use class! it creates a new unique class name, so it doesn't conflict with other classes. This allows you to use Rust's normal scoping/module rules for handling class privacy.

Some major benefits of dominator over other DOM libraries:

Right now it only supports stdweb, but I am very interested in making it work with wasm-bindgen as well (this will likely require some changes/improvements to wasm-bindgen).

There currently isn't a tutorial available, but here is an example of a simple webapp which has a counter:

https://github.com/Pauan/rust-dominator/blob/5d67d80351527e2729cf9bf6e518bea77049209d/examples/counter/src/main.rs

And here is a full featured (and spec compliant) TodoMVC example with routing:

https://github.com/Pauan/rust-dominator/blob/5d67d80351527e2729cf9bf6e518bea77049209d/examples/todomvc/src/main.rs

It is less code than most other TodoMVC examples, and it's probably faster too.

Pauan commented 5 years ago

(The reason I'm making this post here is because it's easier to talk about here, and I will probably miss the next meeting).

thedodd commented 5 years ago

Hey @Pauan thanks for the heads-up. They sound like awesome projects! I'll make sure to bring them up in the next meeting.

Pauan commented 5 years ago

Another heads up that the rustdoc fix is now live, so the tutorial works :tada:

https://docs.rs/futures-signals/%5E0.3.3/futures_signals/tutorial/index.html

Now I need to write a tutorial for dominator.