Easy to follow guide to building SPAs using Rust, WebAssembly and Yew
WebAssembly (wasm) allows code written in languages other than JavaScript to run on browsers. If you haven’t been paying attention, all the major browsers support wasm and globally more than 90% of users have browsers that can run wasm.
Since Rust compiles to wasm, is it possible to build SPAs (Single Page Applications) purely in Rust and without writing a single line of JavaScript? The short answer is YES! Read on to learn more or visit the demo site if you can’t contain your excitement!
We’ll be building a simple ecommerce site called “RustMart” that will have 2 pages:
I’m using this example as it tests the minimal set of capabilities required to build modern SPAs:
Follow this link to install Rust if you haven’t done so already.
Install these Rust tools:
$ cargo install wasm-pack ## Compile Rust to Wasm and generate JS interop code
$ cargo install cargo-make ## Task runner
$ cargo install simple-http-server ## Simple server to serve assets
Create a new project:
$ cargo new --lib rustmart && cd rustmart
We’ll be using the Yew
library to build UI components. Let’s add this and wasm dependencies to Cargo.toml
:
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
yew = "0.17"
wasm-bindgen = "0.2"
Create a new file named Makefile.toml
and add this:
[tasks.build]
command = "wasm-pack"
args = ["build", "--dev", "--target", "web", "--out-name", "wasm", "--out-dir", "./static"]
watch = { ignore_pattern = "static/*" }
[tasks.serve]
command = "simple-http-server"
args = ["-i", "./static/", "-p", "3000", "--nocache", "--try-file", "./static/index.html"]
Start the build task:
$ cargo make build
If you’re new to Rust, I’ve written some guides for beginners which will help you follow this post better.
Let’s start with a simple “hello world” example:
Create static/index.html
and add this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>RustMart</title>
<script type="module">
import init from "/wasm.js";
init();
</script>
<link rel="shortcut icon" href="#" />
</head>
<body></body>
</html>
Add this to src/lib.rs
:
// src/lib.rs
use wasm_bindgen::prelude::*;
use yew::prelude::*;
struct Hello {}
impl Component for Hello {
type Message = ();
type Properties = ();
fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self {
Self {}
}
fn update(&mut self, _: Self::Message) -> ShouldRender {
true
}
fn change(&mut self, _: Self::Properties) -> ShouldRender {
true
}
fn view(&self) -> Html {
html! { <span>{"Hello World!"}</span> }
}
}
#[wasm_bindgen(start)]
pub fn run_app() {
App::<Hello>::new().mount_to_body();
}
Lot of things going on but you can see that we’re creating a new component named “Hello” that renders <span>Hello World!</span>
into the DOM. We’ll learn more about Yew components later.
Start the serve task in a new terminal and load http://localhost:3000
in your browser
$ cargo make serve
It works!! It’s only “hello world” but this is fully written in Rust.
Let’s learn about components and other SPA concepts before proceeding further.
#rust #webassembly #wasm #web-development #developer