I have personally tried and seen various front-end frameworks for Web Apps in Rust. To be honest, they are pretty good and do their job well. But they do have some drawbacks, like a steep curve for understanding the API, and your code getting more complex as your app grows in size.
Now when I see the JS side of things, I see easy adoption and usage. But nah, I'm a Rust fan.
How to make things better? Find flaws and fix them. ๐
Flaws
A natural way of writing UI ๐ค
I felt the lack of a natural way of writing UI. Writing UI should not be hindered by other factors like the language features itself. Like implementing a Trait and all functions along with it to display something simple as a Hello, World!, felt a bit cumbersome.
Message passing is the way to go but not matching them ๐ฅบ
Matching messages to functionality, using a match, might be an extra boilerplate that we can aim to reduce.
Virtual DOM ๐คจ
Current computers are fast enough, that differences between using a Virtual DOM and not using it, are too far less to notice. But yes, if it reduces performance, we can try to get rid of it.
Data centric and composable ๐ฎ
It is a lot easier to build composable UI. Why should the feature not be there?
So, what's next?
I looked at all this and thought, let's write a hypothetical UI first which might use a hypothetical library and then try implementing the library in Rust.
Looking at these snippets, pretty much basic functionality is thought of. Our plan is to implement State variables, update them when changed and bind them to inputs. Now let's come back to implementing the library.
Rethinking States
State update should be asynchronous. Period.
We are aiming for a message passing system, which passes messages to the receiver when the value is updated, and the receiver will be attached to elements and update their value as and when necessary.
This means we don't need diffing or any Virtual DOM.
It should also be bindable to elements and update when an input changes (and also be double way bindable).
It should also be derivable, i.e. a state can derive values from other states, i.e. if State A is deriving its value from State B, when State B updates its value, State A should also do the same.
The solution I am trying to build: Valerie
Enter Valerie. The idea behind Valerie was to enable people to build clean web UI with Rust.
This will show an input which binds to a String, and the length variable derives its value from the string State. And when you type something in the input text field, the data is updated magically.
The above code when compiled, is a .wasm file of 44.7KB (15.1KB gzip).
One thing to notice here is StateAtomic and StateMutex, they are for types implementing Copy and Clone respectively. Internally StateAtomic uses atomics for achieving concurrency and StateMutex uses a mutex.
What if you want to click a button and increment some counter variable?
The above code when compiled, is a .wasm file of 33.1KB (13.5KB gzip).
These are some of the many features of Valerie that I have showed here. The library is still in a very early phase.
Valerie is also a no-std library.
Every piece of UI like a String or div implements the Component trait. You can even extract a part of UI into a different function which returns an impl Component and then reuse it when needed.
Rust follows the principle of Zero-cost abstractions, i.e. you don't have to pay the price of performance for the library features you don't use and whatever you do use you couldn't hand code any better. This means if you don't use a feature provided in Valerie, then it won't end up in the compiled .wasm file.
And comparing WASM with JS, after being received by the browser, your browser has to convert JS into an AST, compile the necessary functions and run it. Now, that's a lot of work. But in the case of WASM, your browser can directly run it using a JIT compiler, as your .wasm file is being received. Because a .wasm file is an optimised portable binary, the browser doesn't have to waste resources optimising it.
Thank you for reading through the article and do take a look at Valerie.