Workshop: Production-ready WebAssembly with Rust
A workshop on Rust for WebAssembly by Alberto Schiabel (@jkomyno). 🤓 This workshop was first presented at RustLab 2023 in Florence, Italy.
The goal of this workshop is allowing experienced Rust engineers to develop WebAssembly modules that can be seamlessly integrated with Node.js and TypeScript codebases. No previous knowledge of WebAssembly is required.
We will be coding through a series of tutorials and test-driven exercises covering topics that every WebAssembly developer likely encounters in production settings:
- understanding
wasm_bindgen
, its uses, limitations, and alternatives - error management and panic handling
Along the way, we'll point out some edge cases that will hopefully help you avoid hours of head-scratching and debugging sessions 😄.
We'll also hint at ways you can overcome WebAssembly's own limitations, proving that you can actually run I/O logic without needing WASI.
Finally, we'll demonstrate how to port a moderately complex Rust library to WebAssembly, applying the concepts learnt during the workshop.
Prerequisites
Before diving into the workshop, let's make sure you have the following tools installed in your system:
- A bash-compatible shell (if you use Windows you can install bash or use Docker, as described below)
- Rust (tested on v
1.73.0
)wasm32-unknown-unknown
compilation target support:rustup target add wasm32-unknown-unknown
wasm_bindgen
:cargo install -f wasm-bindgen-cli --version 0.2.88
cargo watch
:cargo install cargo-watch
- Node.js (tested on v
20.9.0
)pnpm
(tested on v8.9.2
)npm install -g pnpm
- A text editor of your choice (I recommend Visual Studio Code)
Optionally, you can also install the Wasm binary tools from bynarien
. They are not strictly required for the workshop, but they can be useful to inspect the generated WebAssembly modules. If you use Docker, you'll find these tools (e.g., wasm2wat
and wasm-opt
) already installed.
Getting started
Clone the repository and run ./install.sh
to get all the necessary dependencies. This workshop is divided into chapters, containing a mixture of lessons and exercises.
The first chapter is 1-wasm-preliminaries
,
Each chapter focuses on a specific concept about WebAssembly development, and provides some examples and exercises to familiarize with that concept. For each chapter, you will need to complete some Rust code.
To test the exercises, open two terminal tabs side-by-side:
Run ./watch.sh
in each tab, followed by the chapter number. For instance, for the first chapter, if you run ./watch.sh 2
in each tab,
the Rust code will silently be re-compiled to WebAssembly for you via cargo watch
, and tested on Node.js via vitest
.
The Rust source code in ./rust
uses Cargo workspaces. This enables sharing dependencies across the exercise crates for each chapter via the [workspace.dependencies]
attribute in ./rust/Cargo.toml
: rather than having to add a specific version of a dependency in an exercise crate, we can refer to the workspace version instead.
# Cargo.toml in an exercise crate
[dependencies]
wasm-bindgen.workspace = true # <- wasm-bindgen = "0.2.88"
Should run into any issue with the repository and the assumed level of knowledge, please raise your hand and ping us, so we can sort this through together 🪄. Enjoy!
Using Docker
If you prefer to keep your environment clean and use Docker, you have two choices:
- If you use VSCode, you can re-open this repository in a DevContainer by running the
Dev Containers: Reopen in Container
command (you can open the command palette viaCtrl+⇧+P
/Cmd+⇧+P
). - Otherwise, you can spin up a workable environment in your terminal via:
docker compose run --build --rm -it workspace
Chapters overview
- ➡️
1-wasm-preliminaries
- ➡️
2-wasm-bindgen-types
- ➡️
3-wasm-bindgen-classes
- ➡️
4-tsify-types
- ➡️
5-panic-handling
- ➡️
6-error-handling
- ➡️ Demo
This is a work in progress, so stay tuned for more chapters about:
async / await
support- online WebAssembly debugging on Chrome Dev Tools with source maps and breakpoints
WASI
support on Node.js- Publish WebAssembly modules on
npm
- and more!
License
Licensed under MIT License. © Alberto Schiabel.