Rust

A language empowering everyone to build reliable and efficient software. [rust-lang.org]

I think the most important Rust features are:

Official resources

Seed-related notes

  • [IMPORTANT] Debug builds are much bigger and slower. However they contain debug info and their compilation is much faster.

    • Note: Chrome is better for debugging; Firefox is faster.
  • [IMPORTANT] Some crates (e.g. url) and all crates that use them may even double the Seed app size.

  • [IMPORTANT] Some crates are not WASM-compatible or require to enable their additional features. Consult their docs when you encounter compilation problems.

  • Don't try to learn and understand all Rust features and concepts at once. I recommend to follow guides in next chapters - they contain Rust notes, recommendations and links to learning materials.

  • Seed API is designed to be as simple and readable as possible => You don't have to be Rust expert to read and write Seed apps.

  • Even if you are a complete beginner, don't hesitate to write feedback because we can be blind to some API issues, strange behavior or missing documentation.

How to write in Rust

23 General Rules & Recommendations
  1. Rust compiler is your friend.

  2. Document your code, write expressive names, read docs; Testable code snippets in comments are nice.

  3. Learn where to use Result and where panic.

  4. Respect naming conventions.

  5. Learn about the famous couples:

  6. Use early returns where possible.

  7. Don't use one programming paradigm for everything. Learn where to use loops and where to use Iterators.

  8. Use references where possible - e.g. rather use &str instead of String; or &[T] instead of Vec.

  9. Try to write minimum clone calls. When you need to use cheap clone, try to make it explicit - e.g. Rc::clone(&value) [rc docs]

  10. One of the Rust features is safe mutability but use it only when best practices for writing immutable variables and pure functions make your code unreadable, too slow or error-prone.

  11. "Premature optimization is the root of all evil" - especially in Rust because it's one of the fastest language. Don't do anything extra until your benchmarks are ready to test it. Personal examples:

    • When I was writing proxy server in Rust, there were two things that slowed down that proxy multiple times - forgotten println calls in the hot path and slow DNS server... I recommend to zoom-out and fix higher-level issues first.

    • Seed VDOM patching algorithm was fast enough on the first attempt. However it's heavily slowed down by DOM calls. I recommend to look at IO and external dependencies before you try to optimize your Rust code.

  12. Write only cross-platform code and use only Rust tools.

  13. Don't be afraid to write async code.

  14. Learn about the popular libraries like:

  15. Clippy and rustfmt are also your friends. cargo-make is your unofficial friend.

    • You can run command cargo make verify in almost all Seed/my projects. It formats code, lints it by pedantic Clippy and tests it. See the task definition in Rust quickstart.
  16. Write tests and benchmarks (see e.g. Criterion.rs).

  17. Experiment with function parameter types below to find out where there are useful (Note: All of them are used on multiple places in the Seed repo):

    • fn(text: impl AsRef<str>) - AsRef
    • fn(text: impl ToString) - ToString
    • fn(text: impl Into<Cow<'static, str>>) - Cow
    • fn<'a>(text: impl Into<Cow<'a, str>>)
  18. Once in a while:

    • Run rustup update to update your compiler and tools like Clippy.
    • Delete target folder (it's something like node_modules) in your projects to save some space on your disk.
  19. Look at this mem functions:

  20. Use unsafe Rust only for special cases or when it's necessary for your domain (you write operating systems, super fast low-level libraries, etc.) There is only safe code in Seed projects (including Seed's core).

  21. Use "magic" like Any only to improve public API for your users. It always makes the code worse.

  22. Learn to use channels. Docs for standard ones and the ones in some crates:

  23. Write and use macros only if it's really necessary and document them properly. There are many footguns. And IDEs often fight with them - e.g. autocomplete often doesn't work.

    • The exceptions are macros like println, vec, include_str, etc. - see all standard macros.

    • Yes, there are many macros in Seed, but the most of them are used only as an alternative to HTML and are pretty short. And we fixed many bugs inside them already so the rule still applies. We decided to used them after considering many trade-offs.

    • However macros are useful where:

      • There is missing abstraction - e.g. macro stop_and_prevent in drop_zone example.

      • It helps with readability a lot - e.g. macros create_t and t in i18n example.

      • It's hard/impossible to encode everything by proper Rust types - e.g. Seed element macros like div!.

      • It can hide boilerplate and where variable number of parameters is required - e.g. Seed's log! - it formats input parameters and calls Javascript console.log under the hood.

Detailed explanations

Why is Seed written in Rust
  • Performance, low memory consumption and safety are reasons why also an operating system, embedded devices and proxy servers are written in Rust.

  • One of the Rust compilation targets is WebAssembly. It means very fast front-end apps. (Unfortunately there are current limitations because of missing Rust/native browser API, however it's still fast enough even for production apps.)

  • There are many high-quality Rust libraries and tools - we don't have to reinvent wheels while we are developing Seed.

  • Rust is the most loved language. It attracts many skillful developers, contributors and companies.

  • It's pretty easy to contribute, even into the Seed core, once you learn Rust thanks to Rust type system - we (core members) don't have to think about all bad things known from other languages - nulls, typos, unformatted code, memory allocation problems, general anti-patterns, etc. - because we have a good compiler and linters. We can focus on business logic and style during code reviews. There are pull requests with thousands changes from the first-time contributors in the Seed repository.

  • Rust and all Rust tools are cross-platform - it allows you to develop Seed apps on Mac, Windows or Linux without problems.

  • Documentation is priority - official learning resources are very helpful, libraries are well documented and you can write even runnable examples in your code comments.

  • There are many advanced Rust features / APIs that allow us (core developers) to design the best Seed public API for users and THEN we can implement it without problems - in other words: It allows us to hide unnecessary complexity. For instance - we are able to write React-like Hooks without limitations.

  • Rust has been created and is sponsored by Mozilla. Some Firefox parts are already written in Rust. Also other big companies like Amazon, NPM, and Microsoft use Rust. So we expect that Rust will become even more popular and integration with browsers will become easier. And perhaps we'll see some Rust components also in Chrome - Chromium Security article.

Why I want only Rust

I've written commercial or hobby projects in multiple languages (Js, CoffeeScript, TS, Elm, Elixir, PHP, C, C++, C#, Go, ..). However I want to write only in Rust.

Rust is hard to learn even (?) for experienced developers, because they have to unlearn many things and adapt thought process to Rust concepts and best practices. However once you stop fighting the compiler, Rust takes your hand and push you to correct and efficient solutions.

I had similar feeling when I was learning to drive a car - it seems pretty hard/strange from the start but once you get used to it, you know that each control / button / pedal has it's specific place and purpose for a good reason. And it makes even more sense once you learn low-level stuff - e.g. how the transmission and a clutch work.

However steep learning curve isn't bad:

  • It means that Rust doesn't hide real complexity behind too simple models.
  • It's almost impossible for complete beginners to publish incomplete/buggy libraries.

Rust is designed so well that I feel nervous while I'm writing in other languages - I have to do compiler's work again in my head and think about weird things like typos in code, nulls, undefineds, memory leaks, accidental mutations, how to write fast code without mutability, etc. It generates significant cognitive load so I can't focus so much on business logic and other important stuff.

I don't believe that you should use the most suitable language for specific domain or problem at all costs. I think consistency among your / company projects and simplicity should have the highest priority. And Rust is a very universal language so I think it's a good choice for almost all cases.

There are also things that should be improved (and are improving):

  1. Compilation is still slow, but it's not so frustrating now.
  2. It's not possible to compile Rust in a browser so we can't provide live examples but it should be doable once Rust compiler works in WASM.
  3. IDE support still isn't very good because of Rust complex types and macros but thanks to Rust Analyzer it's getting better every day.
  4. Many libraries still aren't WASM/browser-friendly but it's also getting better quickly.
  5. target folder (it's something like node_modules) can be pretty big.

P.S. Write us your opinion about Rust if you are a beginner and learning it.