Intro to WebAssembly via Rust

Intended for Javascript developers (BUT not just)!

Liron Hazan
ITNEXT

--

Disclaimer: This post won’t teach you Rust, the motivation is to get you started quickly into WASM using the amazing wasm-pack tooling on top of the intuitive Rusty ecosystem.

Not so long ago I started to get interested in Rust - How did that happen?

There’s a HYPE around WASM (Web Assembly) and it triggered a need I have with getting my hands dirty with new things.. I wanted to be a part of that party 🎉 🎊 🎈.

I started reading a bit about wasm here and there:

“ WebAssembly is a new type of code that can be run in modern web browsers — it is a low-level assembly-like language with a compact binary format that runs with near-native performance and provides languages such as C/C++ and Rust with a compilation target so that they can run on the web. It is also designed to run alongside JavaScript, allowing both to work together. “

TL,DR With WASM we can:

  • Compile other high level languages code and run the binary with the browser! (so cool 😎).
  • Get (almost) Native performance.
  • Load and execute WASM binaries directly from JavaScript, and exchange data with the JavaScript code.

Came for WASM, stayed for Rust

I could run an “hello world” or other basic example, but I kind of wanted the opportunity of learning another language (new ecosystem, a new world!).

Learning a new language makes you better at your main language cause you stop to wonder of the differences, furthermore you’re looking for familiar patterns and it makes you sharper.

I had to pick C/C++ or Rust, why did I picked Rust?

I picked Rust without any thorough research for my own following reasons:

  1. It’s quite new, new = shiny, and apply lessons learned from older languages and ecosystem “mistakes” or embrace good practices. (I was really intrigued).
  2. It was created by the Mozilla folks which I really appreciate (they did an amazing work with the mdn docs, great community who pushes interesting open source projects such a-frame, servo, mozillaThings etc..
  3. It has a cool name! (my immediate connotation is Megadeth’s album is “Rust in peace”..)
  4. Quick google search showed that it has a “functional” notion, functions can be passed as arguments to other functions, built in high ordered function (such as map, filter fold) for iterables, has Option and Result sum types etc.. and it’s completely immutable by default (unless using “mut”).
  5. I saw it has an async runtime support and I enjoy using non blocking functions, promises are fun, the async await pattern is fun..
  6. I saw it has a good type system.

My reasons are more “development” driven rather performance or efficiency (memory safety, small binary, e.g) driven, I want a language that will let me write in the style I like (functional but not just, with types, async abilities etc..).

Learning resources I used:

There’s a nice course you can watch in pluralsight called: Rust Fundamentals, and I also used the official docs a lot.. I actually think they did a good job. I just can wish I’ll spend my time there as much as I’m doing with MDN :)

Development environment setup

you’ll need to install the rust tools (the compiler, the package manager, the versions manager etc..). Follow the instructions.

📝 NOTE: Cargo is like npm, rustup is like nvm, and rustc is the compiler, I wouldn’t say it’s like tsc cause it’s actually compiles the code into binary rather than to other high level lang.

Back to WASM — Kickstarting a POC

The docs are really great for diving in. If you want a quick start follow this quick manual of installing awesome development tools made for Rust and WASM.

Stuff you should know when starting a project:

In order to kickstart a POC I followed this official manual, it introduces a tool called wasm-pack:

wasm-pack is your one-stop shop for building, testing, and publishing Rust-generated WebAssembly.

I used the wasm-pack in building my POC project, you can hit my POC repo here and web demo there.

For a more “real life use” Angular + Rust + WASM poc checkout my other example.

Let’s review the interesting parts of the project that will make us understand how it all works:

Cargo.toml:

  • The web_sys crate dependency is really interesting — it provides a binding to all API’s provided by the browser (reflects of the C++ rendering engine’s code as far as I understand from reading here).
  • The dependency I interacted with while developing the app was: wasm-bindgen, (Rust library and CLI tool that facilitate high-level interactions between wasm modules and JavaScript).

lib.rs:

Note the#[wasm_bindgen] attribute use, having it will cause a generation of 2 wrappers:

  • JavaScript wrapper which takes JS types to convert to wasm.
  • Rust wrapper which receives wasm types and converts to Rust types.

You can read more about the interaction on this nice post.

The wasm-pack template

Running the webpack build will generate both pkg and dist folders (the webpack config requires a @wasm-tool/wasm-pack-plugin that compiles our Rusty code and generates the pkg with all the needed templates)

If we’ll open the index.js located in the pkg folder we’ll see the following:

import * as wasm from './index_bg.wasm';

/**
*/
export function rust_in_peace() {
wasm.rust_in_peace();
}

You can see how wasm-pack generated a JavaScript wrapper that calls our Rusty function, imported from the WASM binary. Exciting :)

Future Reading — Frontend Rusty frameworks

There are many Rusty open source projects out there in scope of everything, just checkout the awesome-rust repo.

Zooming into Frontend we can aim to develop a “native” Rust (WASM) applications using a framework to make the experience faster / easier / and more scaleable (in terms of the codebase and SW architecture).

I personally aim to checkout Yew(a modern Rust framework for creating multi-threaded front-end web apps with WebAssembly.)

That’s all for now, in case you’ll want to start using WASM+rust I really think that start using wasm-pack is the best way and the docs are really great.

I want to thank Uri Shaked for reviewing this post for me :)

Cheers 🥂

Liron.

--

--