• Paul Butler
Given what we do at Drifting in Space, we talk to a lot of developers pushing the limits of the browser. One trend I’ve noticed is teams building browser-based applications in Rust.
To be clear, I’m not talking about traditional hypertext applications — blogs, social media, or e-commerce. I’m talking about applications that aspire to desktop-class status, but target the browser for low-friction distribution.
For example, a few weeks ago I wrote about applications that render UI directly on the GPU. Of the six mentioned apps that run (or aspire to run) in the browser, all of them are written in Rust.
So we are in a bizarre situation where programmers hand-annotate types, which get thrown away, and then browsers figure out what the types are at runtime.
It’s all a technical feat, but it adds a bunch of complexity.
That’s why WebAssembly was created.
There are a number of languages that support WebAssembly. Rust stands out by being at the lonely intersection of languages that:
- Don’t use a garbage collector, and
- Have modern tooling/package ecosystem.
#1 matters because garbage collection is still WIP in Wasm. This generally rules out anything on the JVM as well as scripting languages.
It’s possible to compile a garbage collector to Wasm and bake it into the module, but this can bloat the module size and hamper runtime performance as the GC has to run in the main thread.
#2 is subjective, but Rust has great tooling. It’s easy to add dependencies to a wealth of libraries (crates), docs for all public crates are live in one place, and the language includes a test framework, formatter, and other tools.
Along the happy path of applications typically built for the browser (think “typical React app”) and don’t use much CPU, this is fine.
When applications do need to optimize for performance, though, complexity comes back with a vengeance.
The advantage of Rust+Wasm is not that you can sprinkle it on an app to get better performance, but that you can have a clear mental model of the performance characteristics of your code. You can know definitively how data will be laid out in memory, or how many memory allocations a block of code will make.
By combining this with a rich collection of standard data types, Rust provides a solid foundation for performant apps.