Seed creator here. For some context, I now code all my websites in HTML, CSS, and targeted JS (ie no frameworks or dependencies). Writing this was a great way to learn the ins and outs of DOM manipulation!
Overall, I'm happy with the way the Seed API turned out, but could never get the performance or package size to a good place.
That said, I love coding in Rust, and use it all the time for embedded!
I'll just say I really enjoy the "Why not Seed?" section of your readme. The honesty is refreshing and it really let me know the plusses/minuses of this.
I agree. The modern hip thing to do that many consider as “having character” is to wax hyperbolically about one’s most likely pretty janky code. I see this a lot with neovim packages and it’s rather annoying, though I can appreciate the enthusiasm.
That's an interesting perspective! As someone considering seed, do you consider it a useful thing to pursue Rust as a frontend language in its current form and given the state of the ecosystem? Obviously you decided to go pretty deep exploring this topic and eventually went a different route but I'd be grateful if you could share some insight here.
At work we built a customer dashboard using Yew (another Rust frontend framework) and absolutely love it. We share API models as a crate between frontend and backend (also Rust) and the same developers work on both. Definitely would never look back, unless larger browser support was a concern. (In our B2B SaaS it hasn't been an issue at all.)
Subjectively, no. Rust is a pleasure to work with for business logic, and some things like dates and times are much easier (via Chrono) than JS, but overall, modern JS is the way to go for DOM manipulation.
For anything low level like embedded, I highly recommend Rust.
For backend/servers, the language is fine, but it has no mature frameworks like Rails or Django. More like Flask analogues.
Not GP but as someone who loves Rust and spent a lot of time trying to use it as a FE language, I settled on F# for my own frontend projects. It has many of the nice things Rust has (discriminated unions, pattern matching, ML inspired syntax) but is much more aimed at typical business logic apps.
With Fable compiler in the frontend and .NET core on backend, you can write the same language on both and even share interfaces, types etc. and it’s just a pleasure to use. If you haven’t tried the .NET ecosystem in the past few years, it’s come a looong way from the old windows only days.
- VDOMs in general have poor performance; they perform unnecessary computations in the diffing algorithm, and even well-designed ones perform extra DOM manipulations, compared to deliberately-written code.
- The Rust WASM files would come out pretty large; a few hundred KB for a minimal app. This is better than some packages using React + common JS dependencies like Lodash and Moment, but with much room for improvement
- DOM manipulation calls made in Rust via WASM(currently!) don't have any performance benefit over the native JS API
So your framework works on DOM? I thought that WASM - DOM interop is not so great and generally WASM apps would work by doing their own rendering on canvas, skipping DOM.
1. The Elm architecture seems to flow nicely in Rust.
2. The way of defining the elements on the page is more Rust like rather than html like. I initially tried Yew which is another similar framework, but since I am a more backend developer, I found writing in a more Rust style more comfortable than writing in a more html-like dsl. Other with different experiences may be more comfortable with more html-like syntax.
3. Very easy to perform REST API calls. I am using Actix for the backend, and I have a shared library that declares the types which both the backend and frontend use. This is one big advantage for using Rust for both backend and frontend, in that you never have to worry about your types getting out of sync.
4. In general as to why Rust for the front end, apart for being able to share types, for more complex algorithms, for me, having a compiled language with an emphasis on safety and that tries to ensure correctness as much as compile time (and especially pattern matching) makes writing complex code more enjoyable for me.
5. Excellent documentation on the Seed website. There are lots of examples and walkthroughs of basics as well as examples of how to do stuff like integrate with Javascript libraries.
Anyway, thanks again to the authors for making and supporting such an awesome library.
- This is one big advantage for using Rust for both backend and frontend, in that you never have to worry about your types getting out of sync.
One thing to be aware of here, you may have users with stale clients after deploying an update to the server. e.g. picture someone who leaves a tab open for a week and then comes back to it and interacts with your app some more without refreshing.
Text based serializations will tend to be more forgiving of changes in the RPC schema (in the sense of erroring out when required fields are missing), while more compact serializations are more likely to incorrectly decode a message when they should fail.
The quick and dirty solution to this is to have a client response handler that checks for a header set on responses to ensure its a compatible version, then prompt a page refresh if not.
One thing you can do in the shared library is to have a version number constant that is always passed in the rpc. That way if the client is stale, it can easily be detected, and you only have to change 1 place when you update the shared structs.
> This is one big advantage for using Rust for both backend and frontend, in that you never have to worry about your types getting out of sync.
Of course this is a hack compared to Rust BE and FE, but I’ve been finding that auto-generating Typescript type definitions from a Pydantic (Python) API works pretty nicely. Of course, what’s going on under the hood there is all a lot uglier than a beautiful modern compiler with an expressive modern type system, but it’s cool that it works.
My most sincere thanks to the author(s) for “Why Not” section. This level of self awareness and transparency makes me so happy; it takes so much guess work and unnecessary back and forth out of the discourse. Again - kudos!
In my opinion, this is the way forward. You cannot convince anyone that does frontend stuff to even try, or EVEN switch to this. We have to prove that this is a viable option, WASM is a viable way, WASM is actually more efficient etc. there are benchmarks and targeted studies... it just seems that browser vendors and devs haven't catched up yet
HTML & CSS is a viable option. HTML is actually more efficient. There are benchmarks and studies, yet they are not needed, as the difference is apparent.
Must we cede control of user agents to random third parties, loading and executing ever more obfuscated, inaccessible, bloated and hostile code? AFAICT, most of the coded loaded in a typical browser serves a user-hostile purpose.
Do you think wasm support should be mandatory for random web pages? Do you think it will not be used to shove even more bloated, hostile etc code? Will it not be used to circumvent/prevent adblockers etc? Do I need to link to a study showing most wasm is used in a hostile manner?
IMO, wasm is a net-negative on the web. Even though it does have significant good uses. It should be (or should have been) opt-in for specific pages that have a good use for it.
So often people get emotional about languages and frameworks. They’re tools, and tools have trade offs. The “Why Not” section recognizes that. Super impressive.
I’d call Sycamore fairly different from Svelte; both eschew VDOM, but they do it in decidedly different ways, which I would summarise as Svelte being a component-oriented compiler primarily modelling reactivity implicitly, but Sycamore being a data-oriented library almost incidentally capable of producing HTML, exclusively modelling reactivity explicitly.
Svelte is a compiler through and through, providing and requiring its own syntax for things like conditionals and iteration, and declaring reactivity at the syntax level, inextricably tying its reactivity to properties on components, except for stores which allow regular JavaScript to get involved in reactivity (though components also get special support for stores via the $foo syntax). Dirty tracking happens at the component level.
Sycamore, on the other hand, is straight Rust (though typically assisted by procedural macros, which I will admit weakens the distinction), with only explicit reactivity (like Svelte’s stores), but keeping track of dependencies at runtime (more like Ember.js) and with things like conditionals handled as regular Rust code, and iteration as just a component that gets given an iterable rather than needing dedicated constructs. Dirty tracking happens at the data level.
(Qualifier: I’m expert with Rust and Svelte, fairly familiar with Ember.js, and quite familiar with some of Sycamore’s similar precursors, but I have only skimmed Sycamore, reading docs and a bit of code; I haven’t actually used it.)
This is a great approach. Ie, declarative coding GUIs (like webapps) is nice, but VDOM is performance overhead, ie unnecessary computation. I haven't looked into how Svelte (Or Sycamore) do it, but being able to compile declarative code into targeted DOM manipulation seems like a best-of-both-worlds.
Looking the home page (which looks to be built with seed-rs), a ~500k wasm file is loaded.
The static part loads fairly fast, but none of the links work until after the wasm loads (you can tell because the header changes)
Looks like the entire site is in the wasm file as no additional network requests are made. Doesn't seem great for general purpose web sites (like your home page).
Is that 500k with or without gzip? With gzip, that would be huge.
Either way there are certain techniques like bundle-splitting and hydration that will probably have to be reinvented for these WASM frameworks, unfortunately. For the moment they're probably better suited to high-complexity browser-based tooling that needs the extra performance, vs simple crud sites.
Edit: on second thought, for an entire multi-page site in one bundle this wouldn't be super huge. I'm used to smaller numbers but I'm also used to split-bundles.
Not that I disagree — it's rather steep — but not super unlike many react/vue based sites.
Frameworks like Next.js can help by adding seamless server side rendering so at least your links will work before your js/wasm is loaded. Maybe seed-rs can move into that direction as well.
It works fine for me on Chrome (Linux or Android), Edge(ium, on Linux and Windows) and Firefox (Linux, for some reason not Android). It fails on Gnome Web (which is WebKit GTK), which is the closest I could get to Safari, because of SharedArrayBuffers being unavailable [0]. It seems like WebKit hasn't re-enabled them since the first Spectre mitigations like Chromium and Firefox have.
One reason it could fail for you on Chrome is that perhaps you tested on iOS; Chrome on iOS shouldn't make or break web applications because Apple forces WebKit onto every browser on that platform, so they're all Safari with a skin. A broken website in iOS Safari is usually broken in all other browsers by Apple's design.
Otherwise the code should work fine on up-to-date Chrome across all real Chrome platforms, unless you specifically toggled flags...
Date inputs were standardized with HTML5, but browser implementations are of variable quality (and, important to designers, variable default look-and-feel, and limited, IIRC, customizability).
There are native solutions in browsers. I think they mean that they'd have to use their own custom "rust to dom" ones, if they didn't like the native browser ones (they do have some limitations around styling and formatting)
Very very recently some do, and they aren't amazing. I'm not even sure Firefox 93 is officially released yet? Safari support was less than a year ago. https://caniuse.com/?search=datetime-local
Don't get me wrong. I'm glad we finally have some consensus, but this should have happened before ES6 (2015!) IMO. jQuery had a date picker before 2009 at least (probably earlier, but I'm not sure).
Author of sauron here, Yes sauron[0] is very much elm-like than any of the other rust framework, and it's very fast. How fast? Fast enough to be used in a text-editor[1] at ~15ms typing latency. It also suited application that has recurring events such as animation[2]
It also supports server-side rendering, and is used in one of my other opensource project svgbob[3]
Overall, I'm happy with the way the Seed API turned out, but could never get the performance or package size to a good place.
That said, I love coding in Rust, and use it all the time for embedded!
Dead Comment
For anything low level like embedded, I highly recommend Rust.
For backend/servers, the language is fine, but it has no mature frameworks like Rails or Django. More like Flask analogues.
With Fable compiler in the frontend and .NET core on backend, you can write the same language on both and even share interfaces, types etc. and it’s just a pleasure to use. If you haven’t tried the .NET ecosystem in the past few years, it’s come a looong way from the old windows only days.
Do you have any more details on that? I'm curious how close this got, and what were the main issues (on both size and speed).
- VDOMs in general have poor performance; they perform unnecessary computations in the diffing algorithm, and even well-designed ones perform extra DOM manipulations, compared to deliberately-written code.
- The Rust WASM files would come out pretty large; a few hundred KB for a minimal app. This is better than some packages using React + common JS dependencies like Lodash and Moment, but with much room for improvement
- DOM manipulation calls made in Rust via WASM(currently!) don't have any performance benefit over the native JS API
I am using this for my personal project: https://www.biblemaze.com which is a Bible trivia game.
Here are some things I like about Seed:
1. The Elm architecture seems to flow nicely in Rust.
2. The way of defining the elements on the page is more Rust like rather than html like. I initially tried Yew which is another similar framework, but since I am a more backend developer, I found writing in a more Rust style more comfortable than writing in a more html-like dsl. Other with different experiences may be more comfortable with more html-like syntax.
3. Very easy to perform REST API calls. I am using Actix for the backend, and I have a shared library that declares the types which both the backend and frontend use. This is one big advantage for using Rust for both backend and frontend, in that you never have to worry about your types getting out of sync.
4. In general as to why Rust for the front end, apart for being able to share types, for more complex algorithms, for me, having a compiled language with an emphasis on safety and that tries to ensure correctness as much as compile time (and especially pattern matching) makes writing complex code more enjoyable for me.
5. Excellent documentation on the Seed website. There are lots of examples and walkthroughs of basics as well as examples of how to do stuff like integrate with Javascript libraries.
Anyway, thanks again to the authors for making and supporting such an awesome library.
One thing to be aware of here, you may have users with stale clients after deploying an update to the server. e.g. picture someone who leaves a tab open for a week and then comes back to it and interacts with your app some more without refreshing.
Text based serializations will tend to be more forgiving of changes in the RPC schema (in the sense of erroring out when required fields are missing), while more compact serializations are more likely to incorrectly decode a message when they should fail.
Of course this is a hack compared to Rust BE and FE, but I’ve been finding that auto-generating Typescript type definitions from a Pydantic (Python) API works pretty nicely. Of course, what’s going on under the hood there is all a lot uglier than a beautiful modern compiler with an expressive modern type system, but it’s cool that it works.
Dead Comment
Must we cede control of user agents to random third parties, loading and executing ever more obfuscated, inaccessible, bloated and hostile code? AFAICT, most of the coded loaded in a typical browser serves a user-hostile purpose.
Do you think wasm support should be mandatory for random web pages? Do you think it will not be used to shove even more bloated, hostile etc code? Will it not be used to circumvent/prevent adblockers etc? Do I need to link to a study showing most wasm is used in a hostile manner?
IMO, wasm is a net-negative on the web. Even though it does have significant good uses. It should be (or should have been) opt-in for specific pages that have a good use for it.
AFAIK Seed and Yew target the VDOM stuff which has always been an unnecessary overhead, Sycamore does what Svelte does.
It's very early days for Rust/WASM/Frontend, but all of this progress is very promising.
Svelte is a compiler through and through, providing and requiring its own syntax for things like conditionals and iteration, and declaring reactivity at the syntax level, inextricably tying its reactivity to properties on components, except for stores which allow regular JavaScript to get involved in reactivity (though components also get special support for stores via the $foo syntax). Dirty tracking happens at the component level.
Sycamore, on the other hand, is straight Rust (though typically assisted by procedural macros, which I will admit weakens the distinction), with only explicit reactivity (like Svelte’s stores), but keeping track of dependencies at runtime (more like Ember.js) and with things like conditionals handled as regular Rust code, and iteration as just a component that gets given an iterable rather than needing dedicated constructs. Dirty tracking happens at the data level.
(Qualifier: I’m expert with Rust and Svelte, fairly familiar with Ember.js, and quite familiar with some of Sycamore’s similar precursors, but I have only skimmed Sycamore, reading docs and a bit of code; I haven’t actually used it.)
The static part loads fairly fast, but none of the links work until after the wasm loads (you can tell because the header changes)
Looks like the entire site is in the wasm file as no additional network requests are made. Doesn't seem great for general purpose web sites (like your home page).
Either way there are certain techniques like bundle-splitting and hydration that will probably have to be reinvented for these WASM frameworks, unfortunately. For the moment they're probably better suited to high-complexity browser-based tooling that needs the extra performance, vs simple crud sites.
Edit: on second thought, for an entire multi-page site in one bundle this wouldn't be super huge. I'm used to smaller numbers but I'm also used to split-bundles.
Frameworks like Next.js can help by adding seamless server side rendering so at least your links will work before your js/wasm is loaded. Maybe seed-rs can move into that direction as well.
It doesn't really test Seed, but I guess Seed just works?! :shrug:
One reason it could fail for you on Chrome is that perhaps you tested on iOS; Chrome on iOS shouldn't make or break web applications because Apple forces WebKit onto every browser on that platform, so they're all Safari with a skin. A broken website in iOS Safari is usually broken in all other browsers by Apple's design.
Otherwise the code should work fine on up-to-date Chrome across all real Chrome platforms, unless you specifically toggled flags...
[0]: https://caniuse.com/mdn-javascript_builtins_sharedarraybuffe...
Anyone else think it’s insane that we’re still implementing JS date pickers in 2021? How was this not native like 20 years ago?
Date inputs were standardized with HTML5, but browser implementations are of variable quality (and, important to designers, variable default look-and-feel, and limited, IIRC, customizability).
Don't get me wrong. I'm glad we finally have some consensus, but this should have happened before ES6 (2015!) IMO. jQuery had a date picker before 2009 at least (probably earlier, but I'm not sure).
Unique or not, I bet it makes working with the borrow-checker a whole lot easier
It also supports server-side rendering, and is used in one of my other opensource project svgbob[3]
[0]: https://github.com/ivanceras/sauron
[1]: https://ivanceras.github.io/ultron/
[2]: https://ivanceras.github.io/futuristic-ui/
[3]: https://ivanceras.github.io/svgbob-editor/