Quickstart

Our first example is a counter that can be incremented or decremented. The complete code is found here

I assume you already installed rust and cargo binaries already. If not, then you can install by issuing the following command from your terminal.

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

To create a rust project with sub code in it. Issue the command:

cargo new --lib counter

This will create a library crate with counter as the package name.

Edit the Cargo.toml file to set the library crate-type to cdylib1.

1[package]
2name = "counter"
3version = "0.1.0"
4authors = ["Your name <urmail@provider.domain>"]
5edition = "2018"
6
7[lib]
8crate-type = ["cdylib"]
9
10
11[dependencies]
12sauron = "0.32"

We also need to add sauron as a dependecy of the project.

Add this code to src/lib.rs

src/lib.rs

1use sauron::html::text;
2use sauron::prelude::*;
3use sauron::{node, Cmd, Component, Node, Program};
4
5#[derive(Debug)]
6pub enum Msg {
7    Increment,
8    Decrement,
9}
10
11pub struct App {
12    count: i32,
13}
14
15impl App {
16    pub fn new() -> Self {
17        App { count: 0 }
18    }
19}
20
21impl Component<Msg> for App {
22    fn view(&self) -> Node<Msg> {
23        node! {
24            <main>
25                <input type="button"
26                    value="+"
27                    key="inc"
28                    on_click=|_| {
29                        Msg::Increment
30                    }
31                />
32                <div>{text(self.count)}</div>
33                <input type="button"
34                    value="-"
35                    key="dec"
36                    on_click=|_| {
37                        Msg::Decrement
38                    }
39                />
40            </main>
41        }
42    }
43
44    fn update(&mut self, msg: Msg) -> Cmd<Self, Msg> {
45        match msg {
46            Msg::Increment => self.count += 1,
47            Msg::Decrement => self.count -= 1,
48        }
49        Cmd::none()
50    }
51}
52
53#[wasm_bindgen(start)]
54pub fn main() {
55    Program::mount_to_body(App::new());
56}

And finally our index.html file

1<html>
2  <head>
3    <meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
4    <title>Counter</title>
5  </head>
6  <body>
7    <script type=module>
8        import init from './pkg/counter.js';
9        init().catch(console.error);
10    </script>
11  </body>
12</html>

This is the minimal set of files in order to compile and run our project as a web application. Next, we need to install wasm-pack, to simplify our workflow of our project to compile to webassembly.

cargo install wasm-pack

Invoking the command:

wasm-pack build --release --target=web

wasm-pack adds arguments to the rust compiler to compile our code into webassembly and link it to a javascript module. All of this is abstracted with wasm-pack, so we don't have to think about it. We only care about our js file ./pkg/counter.js that is generated in pkg directory in our project folder.

Next, we need to statically serve the index.html such that the browser can run the .wasm2 binary in the browser

1

use cdylib for crate-type if you want to build it as wasm entry point crate. If you also want this crate as a reusable component from your other crate, then you can add rlib as crate-type.

1[lib]
2crate-type = ["cdylib", "rlib"]
2

wasm files can not be executed in the browser unless serve from the same domain as the index.html which reference it.