Experimenting With Rust And WebAssembly
The only way to discover the limits of the possible is to go beyond them into the impossible.
—Arthur C. Clark
I’ve been programming for the last few years primarily in web development, so it’s not too often I get to use a powerful low-level programming language like Rust. Rust is known for it’s unparalleled safety and performance. My interest was more than stoked after seeing Rust win most beloved programming language on Stack Overflow surveys year after year. I was fascinated to learn I could use Rust code in the frontend by compiling Rust code into WebAssembly so I dove in head first and created a snake game to see how it all worked.
Why Rust and WebAssembly?
There are numerous articles that talk about why so many developers love Rust and understandably so. Rust is a modern programming language designed for powerful type safety, fearless concurrency, and unparalled performance. That’s nice and all but how does that help web developers? With Rust’s excellent tooling, we can compile our Rust code down to WebAssembly which aims to perform at near native code. JavaScript is an amazing language and I’m sure we all have a special place for it in our hearts but there is a limit to what an interpreted language can do.
There are many use cases for WebAssembly like image proccessing, music applications, CAD applications, and so many other uses. There are so many success stories from companies like Figma and Vercel that it’s easy to see why many are turning to Rust and WebAssembly to innovate new solutions on the web.
Building the Snake Game
As part of my initial foray into Rust, I signed up for a course on Udemy. The entire logic of the game was built in Rust and then compiled down into WebAssembly. One of the perks of using Rust is that the tooling, wasm-pack, generates all of the necessary TypeScript definitions and files based off of the types found in the Rust code. Importing our new wasm modules is a trivial task:
import init, { World, Direction, GameStatus } from "snake_game";
init().then((wasm) => {
// use wasm modules here
}
// or using async/await syntax
async function start() {
const wasm = await init();
//use wasm modules here
}
You can see the full example here. Aside from the logic within Rust, once all of the modules are imported into JavaScript there isn’t anything special you need to do. I think this makes using WebAssembly incredibly powerful because only pieces of an application can be surgically replaced with WebAssembly code to maximize performance and open up new possibilities.
There is definitely a slight shock when you first start coding in Rust after working with JavaScript for so long. It won’t be too bad if you’re already familiar with languages like Java, C/C++, or C#.. Rust actually feels modern after writing it for a bit and I have to say there’s something elegant about it. One thing I noticed is that the compiler is so amazing at pointing out what’s wrong. It’s like having a coach right there next to you, yelling in your ear about the error on line 52.
The rust borrow checker will also require some studying but the idea is simple: at all times in your code you must explicitly manage the ownership of a variable. The borrow checker is unique to Rust and is why handling memory allocation in Rust is easy. I think the borrow checker makes code more deliberate and well thought out. It’s less of a hassle and in the end it enhances developer experience.
The Cons
Rust has it’s own quirks and a steep learning curve compared to other languages making the adjustment period long. It’s not like other languages so you’ll certainly be taken aback if you’re coming from a language like Python or JavaScript. Rust’s ownership model is innovative and is certainly brilliant but the for uninitiated there’s going to be long period of trial-and-error. It’s not beginner friendly at all. Learning Rust means adopting an entirely new paradigm to development.
While the process was rewarding and being able to essentially run Assembly code in the browser is awesome, there is also the additional toolchain and ecosystem we have to navigate. While tooling is always improving, nothing is going to beat the tooling we have already built around JavaScript/TypeScript for developing a majority of applications — at least not for awhile.
Where To From Here?
Rust’s ascent in the programming world is undeniable, with an ever increasing number of developers using it. My cursory explorations thus far have demonstrated to me the potential impact Rust will have in the software development landscape. We’re in truly exciting times!
I’ve already built a small web server with Rust for a to-do application but now I’m interested in building a robust web service with Rust. It’s clear to see Rust is here to stay and so many are finding excellent use for it in their codebase. I’m now closely following the development of the Actix web framework and am so excited to build some new cool stuff. By sharing my experiences and the projects I undertake, I hope to inspire others to explore new possibilities and push the boundaries of what can be achieved.