DEV Community

mtwtkman
mtwtkman

Posted on • Updated on

Write a frontend application with Rust

yew helps you making a frontend application.
I remind how to do it.

Prerequests

I need some tools to do it.
Basically it is clear what I need by reading yew official document.

Now I choose wasm-pack to build a wasm application.

$ cargo install wasm-pack
$ cargo new myapp
$ cd myapp

So, I need edit Cargo.toml to build using wasm-pack.

[dependencies]
yew = { version = "0.14.3", features = ["web_sys"] }
wasm-bindgen = "0.2"

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

Done.

Write Rust code

I defined my rust application as lib type although I created my project as bin type.
So I modified my project looks like now.

myapp
  - src
    - app.rs  # my application body (renamed from `main.rs`)
    - lib.rs  # entrypoint of wasm application (added by manually)
  - Cargo.toml
  - Cargo.lock

app.rs looks like below.

use yew::prelude::*;

pub struct Model {
    link: ComponentLink<Self>,
    value: i64,
}

pub enum Msg {
    AddOne,
    SubOne,
}

impl Component for Model {
    type Message = Msg;
    type Properties = ();
    fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
        Self {
            link,
            value: 0,
        }
    }

    fn update(&mut self, msg: Self::Message) -> ShouldRender {
        match msg {
            Msg::AddOne => self.value += 1,
            Msg::SubOne => self.value -= 1,
        }
        true
    }

    fn view(&self) -> Html {
        html! {
            <div>
                <button onclick=self.link.callback(|_| Msg::AddOne)>{ "+1" }</button>
                <button onclick=self.link.callback(|_| Msg::SubOne)>{ "-1" }</button>
                <p>{ self.value }</p>
            </div>
        }
    }
}

And lib.rs is

use yew;
use wasm_bindgen::prelude::*;

mod app;

#[wasm_bindgen]
pub fn start() {
    yew::initialize();
    yew::App::<app::Model>::new().mount_to_body();
}

wasm_bindgen allows to us using our Rust code in javascript world, awesome.

Build Rust code to wasm application

After wrote Rust code with yew, I must run wasm-pack for building it.

$ wasm-pack build

So, wasm-pack without any parameter generates pkg directory.
pkg directory has many stuffs that I don't know there are, but I know that there work fine :-).

Write my frontend code

Now I have wasm code generated by Rust code.
All I need is using it, HOW?
You know anytime MDN documents helps us, refer this article.

$ mkdir site
$ cd site
$ npm init
$ npm i -D webpack webpack-dev-server webpack-cli
$ npm i ../pkg

OK, next I write webpack.config.js

const path = require('path');
module.exports = {
  entry: './index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'index.js',
  },
  mode: 'development',
  devServer: {
    host: '0.0.0.0',
    port: 55301,
  },
};

And index.html and inde.js which calls the wasm application.

index.js is

const js = import('./node_modules/myapp/myapp.js');
js.then(js => js.start());

index.html is

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>anond browser</title>
    </head>
    <body>
        <script src="./index.js"></script>
    </body>
</html>

Run server

Now I can ensure my application works fine.

$ npx webpack-dev-server

Alt Text

Looks good.

HOT RELOAD?

Yes, of course.
I modify my Rust code while running dev server.

...
html! {
    <div>
        <h1>{ "Modifying" }</h1>
        ...
    </div>
}
...

Build manually.

$ wasm-pack build

After building, dev server detected this changing and reloaded the built wasm application. It means my browser was refreshed and shows new sentence added by me.

Alt Text

I just said AWESOME EASY, yeah.

Top comments (2)

Collapse
 
qm3ster profile image
Mihail Malo

If you need server rendering today, I recommend looking at github.com/chinedufn/percy,
and if you don't, github.com/Pauan/rust-dominator.
The latter beats Svelte performance and memory usage, by using the right concepts like github.com/ryansolid/solid does for JS. You might even want to explore using the underlying github.com/Pauan/rust-signals for non-frontend purposes.

Collapse
 
mtwtkman profile image
mtwtkman

I appriciate your comment!
They are the ones I hardly knew. I gonna play with them.