Skip to content

quickstart

Jovansonlee Cesar edited this page Oct 13, 2021 · 1 revision

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 cdylib[^0].

[package]
name = "counter"
version = "0.1.0"
authors = ["Your name <urmail@provider.domain>"]
edition = "2018"

[lib]
crate-type = ["cdylib"]


[dependencies]
sauron = "0.32"

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

Add this code to src/lib.rs

src/lib.rs

use sauron::html::text;
use sauron::prelude::*;
use sauron::{node, Cmd, Component, Node, Program};

#[derive(Debug)]
pub enum Msg {
    Increment,
    Decrement,
}

pub struct App {
    count: i32,
}

impl App {
    pub fn new() -> Self {
        App { count: 0 }
    }
}

impl Component<Msg> for App {
    fn view(&self) -> Node<Msg> {
        node! {
            <main>
                <input type="button"
                    value="+"
                    key="inc"
                    on_click=|_| {
                        Msg::Increment
                    }
                />
                <div>{text(self.count)}</div>
                <input type="button"
                    value="-"
                    key="dec"
                    on_click=|_| {
                        Msg::Decrement
                    }
                />
            </main>
        }
    }

    fn update(&mut self, msg: Msg) -> Cmd<Self, Msg> {
        match msg {
            Msg::Increment => self.count += 1,
            Msg::Decrement => self.count -= 1,
        }
        Cmd::none()
    }
}

#[wasm_bindgen(start)]
pub fn main() {
    Program::mount_to_body(App::new());
}

And finally our index.html file

<html>
  <head>
    <meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
    <title>Counter</title>
  </head>
  <body>
    <script type=module>
        import init from './pkg/counter.js';
        init().catch(console.error);
    </script>
  </body>
</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 .wasm[^wasm] binary in the browser

[^0]: 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.

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

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

Clone this wiki locally