Rustのyewを使ってみる

みなさん、Yewをご存知でしょうか(イュウみたいなユゥみたいな読み方をします)。

RustマクロでReactのJSXのようなHTML表記をして、WebAssemblyに変換して動かすことができるライブラリです。

参考 yewgithub.com

半年くらい前に実験的にこれを使って遊んでみたのを思い出したので書き置きしておきます。

セットアップ

なぜかYewはnightly版のRustでないと動きません。

$ rustup install nightly
$ rustup default nightly

こうしてやりましょう。

つぎにWebAssemblyコンパイルを利用するために以下のようにします。

$ rustup target add wasm32-unknown-unknown

そして後に使うコマンドのために、以下をcargo-webをインストールします。

$ cargo install cargo-web

セットアップはこれにて完了です。

使ってみる

以下のようにプロジェクト作っていきます。

$ cargo new [プロジェクト名]

そしてこのプロジェクトにYewを追加してやりましょう。

$ cargo add yew

+1ボタンを押すと数が1ずつ増えていくだけのクソサンプルコードが以下になります。

use yew::{html, Component, ComponentLink, Html, Renderable, ShouldRender};

struct Model { 
    state: State
}

struct State {
    counter: i32,
}

impl State {
    fn count_up(&mut self) {
        self.counter = self.counter + 1
    }
}

enum Msg {
    Count()
}

impl Component for Model {

    type Message = Msg;
    type Properties = ();

    fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self {
        Model {
            state: State {
                counter: 0,
            },
        }
    }

    fn update(&mut self, msg: Self::Message) -> ShouldRender {
        match msg {
            Msg::Count() => {
                self.state.count_up();
            }
        }
        true
    }
}

impl Renderable<Model> for Model {
    fn view(&self) -> Html<Self> {
        html! {
          <>
            <p>{&self.state.counter.to_string()}</p>
            <button onclick=|_| Msg::Count(), >{ "+1" }</button>
          </>
        }
    }
}

fn main() {
    yew::start_app::<Model>();
}

クセのあるところ

Reactの場合、”class”がJavaScriptの予約語となっているため、”className”なる悪魔的な独自文を持ち出していますが、Rustを使っているYewはそのような心配はありません。

しかし。

テキストノード

まず、上記のサンプルを見ていただければわかりますが、HTMLのテキストノードに当たる部分をナマで書くことができません。

<button>+1</button>

ではなく、

<button>{ "+1" }</button>

と書かざるを得ないのです。

まあエディタのオートコンプリートがあればそこまで生産性に支障はないでしょうが、クセであることは確かです。

属性ノード

加えて、HTMLの属性ノード(いわゆるアトリビュート)を記述したあと、必ずコンマが必要になっています。

これはおそらく、onclickなどのイベント記述にクロージャを使えるようにしていると構文解釈が複雑になりすぎてしまうからでしょう。

慣れれば問題ないですが、HTMLとは結構離れてしまっています。クセです。

まとめ

バンドルサイズは現実的な値ですが、処理速度や生産性の面でまだまだ実用に耐えるものではありません。なので当分Angularにお世話になります。

が、WebAssemblyの可能性を知る一つの例としては面白いんじゃないでしょうか。

余談ですが、Rustのこの本を家に置いてあります。