RustでWebアッセンぶる　入門(環境構築)編

[WEBエンジニア勉強会 #13 (東京都, 渋谷)](https://web-engineer-meetup.connpass.com/event/128855/)にて10分LTをさせていただくことにしました。抽選なのでまだ未確定なのですが。

ネタは今考えてます。
というか最近気になっているwebassemblyというやつを触っておいてみようかなと。WEBエンジニア界隈だと認知度どんなもんなのか気になります。
どうやって個性を出すかはこれから。

# WebAssemblyとは
wikipedia様によるとこんな感じでごわす
>WebAssemblyは、ウェブブラウザのクライアントサイドスクリプトとして動作するプログラミング言語（低水準言語）である。wasmとも称されており、ブラウザ上でバイナリフォーマットの形で実行可能であることを特徴とする[2]。2017年現在開発が進められており、最初の目標としてCとC++からのコンパイルをサポートすることを目指している[3]他、Rustがバージョン1.14以降で[4]、Goがバージョン1.11以降で[5]、Kotlin/Nativeがバージョン0.4以降で[6]で対応するなど、他のプログラミング言語のサポートも進められている。
https://ja.wikipedia.org/wiki/WebAssembly

へー。kotlinも？知らんかった。
簡単に言うと、ブラウザでコンパイル済みのコードを動かす仕組みって事だと思う。
JSだとちょっとしんどいような時に使う想定なのでブラウザゲームとかで活用できるのかも。
Web(JS) + アセンブリ言語って感じ？

# 用語
| Left align       |       Right align |
|:-----------------|------------------:|
| .wat|"WebAssembly Text"。読める形式のwasmファイル|
| .wasm|バイナリ形式のwasmファイル。|

For reference, here is a factorial function in ```wat```:

```.wat
(module
  (func $fac (param f64) (result f64)
    get_local 0
    f64.const 1
    f64.lt
    if (result f64)
      f64.const 1
    else
      get_local 0
      get_local 0
      f64.const 1
      f64.sub
      call $fac
      f64.mul
    end)
  (export "fac" (func $fac)))
```

# まずはやる
基本、みんなこれをやるみたいです。
Rust 🦀 and WebAssembly 🕸
https://rustwasm.github.io/docs/book/

## setup
>You will need the standard Rust toolchain, including rustup, rustc, and cargo.

当然ながらRustが使える環境が必要です。versionは1.3.0以上がいいらしいです。

```
$ rustc --version
rustc 1.34.1 (fc50f328b 2019-04-24)
```

ちなみにwin10Proでやります。

## wasm-pack インストール

https://rustwasm.github.io/wasm-pack/installer/
からインストールします。
ちなみにrustupにPATHが通ってないと下記のように怒られます。つまりwindowsの場合とcmd上でPATHが通ってないと怒られる。

```
failed to find an installation of `rustup` in `PATH`, is rustup already installed?
Press enter to close this window...
```

なんで結局、rustupが通ってるgit-bashにて```curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh``` を実行しました。
おまじない的に下記も。

```
$ cargo install cargo-generate
$ npm install npm@latest -g
$ npm --version
6.9.0
```

## Clone the Project Template

```
$ cargo generate --git https://github.com/rustwasm/wasm-pack-template
```

チュートリアル通り、```wasm-game-of-life``` っていうプロジェクト名にします。
構造はこんな感じ。

```bash
wasm-game-of-life/
├── Cargo.toml
├── LICENSE_APACHE
├── LICENSE_MIT
├── README.md
└── src
    ├── lib.rs
    └── utils.rs
```

src/lib.rsっていうのがスクリプトの本体で、単にjsのalertを実行するだけっぽいです。

```Rust:src/lib.rs
extern crate cfg_if;
extern crate wasm_bindgen;

mod utils;

use cfg_if::cfg_if;
use wasm_bindgen::prelude::*;

cfg_if! {
    // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
    // allocator.
    if #[cfg(feature = "wee_alloc")] {
        extern crate wee_alloc;
        #[global_allocator]
        static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
    }
}

#[wasm_bindgen]
extern {
    fn alert(s: &str);
}

#[wasm_bindgen]
pub fn greet() {
    alert("Hello, wasm-game-of-life!");
}
```

```#[wasm_bindgen]``` ってマクロがwasmでfunction使うための儀式なのかな。

## Build the Project

さっきまでのはバックエンド側（・・という言い方もちょっと違うのかな？）。
お次はフロント部分です。nodejsの部分すね。

プロジェクトのディレクトリにて下記を実行

```
$ wasm-pack build
```
なんか``` warning: function is never used: `set_panic_hook` ```っていう警告が出たりはしましたが、pkgディレクトリというのが作られました。

```bash:wasm-game-of-life/
pkg/
├── package.json
├── README.md
├── wasm_game_of_life_bg.wasm
├── wasm_game_of_life.d.ts
└── wasm_game_of_life.js
```

## Putting it into a Web Page
いよいよ動かしてみる。
まず、webページのテンプレを作る。
プロジェクトのディレクトリで実行します。

```
$ npm init wasm-app www
npx: 1個のパッケージを4.699秒でインストールしました。
🦀 Rust + 🕸 Wasm = ❤
```

(カニ+蜘蛛の巣=ハートって何やねん。巣に引っかかっとるがな。)

お次はwwwディレクトリができました。

```bash:wasm-game-of-life/
www/
├── bootstrap.js
├── index.html
├── index.js
├── LICENSE-APACHE
├── LICENSE-MIT
├── package.json
├── README.md
└── webpack.config.js
```

ちなみにindex.jsはこんな感じ。

```js:www/index.js
import * as wasm from "hello-wasm-pack";

wasm.greet();
```

お次はnpmフォルダで``` npm install ``` をして依存モジュールを入れておきます。
その次はpkgフォルダで``` npm link``` 実行しろとあるので実行します。
プロジェクトフォルダ外のモジュールにlinkを張るのかな。

```
$ npm link
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN wasm-game-of-life@0.1.0 No repository field.
npm WARN wasm-game-of-life@0.1.0 No license field.

up to date in 0.351s
found 0 vulnerabilities

C:\Users\user\AppData\Roaming\npm\node_modules\wasm-game-of-life -> C:\r\wasm-game-of-life\pkg
```

さらにはwwwフォルダで以下を。

```bash
$ npm link wasm-game-of-life
C:\r\wasm-game-of-life\www\node_modules\wasm-game-of-life -> C:\Users\user\AppData\Roaming\npm\node_modules\wasm-game-of-life -> C:\r\wasm-game-of-life\pkg
```

最後に```www/index.js```をmodifyします。

```js:www/index.js
import * as wasm from "wasm-game-of-life";

wasm.greet();
```

## Serving Localy
いよいよ実行です。
ただただalert()を実行するだけなのに長旅でした。

```
$ npm run start

> create-wasm-app@0.1.0 start C:\r\wasm-game-of-life\www
> webpack-dev-server

i ｢wds｣: Project is running at http://localhost:8080/
i ｢wds｣: webpack output is served from /
i ｢wdm｣: Hash: 6571fe1da17c92a46098
Version: webpack 4.30.0
Time: 742ms
Built at: 2019-05-02 19:00:28
                           Asset          Size  Chunks             Chunk Names
                  0.bootstrap.js      3.55 KiB       0  [emitted]
7144487deacc988b3b63.module.wasm  unknown size       0  [emitted]
                    bootstrap.js       355 KiB    main  [emitted]  main
                      index.html     175 bytes          [emitted]
Entrypoint main = bootstrap.js
[0] multi (webpack)-dev-server/client?http://localhost ./bootstrap.js 40 bytes {main} [built]
[../pkg/wasm_game_of_life.js] 981 bytes {0} [built]
[./bootstrap.js] 279 bytes {main} [built]
[./index.js] 58 bytes {0} [built]
[./node_modules/ansi-html/index.js] 4.16 KiB {main} [built]
[./node_modules/events/events.js] 13.3 KiB {main} [built]
[./node_modules/loglevel/lib/loglevel.js] 7.68 KiB {main} [built]
[./node_modules/querystring-es3/index.js] 127 bytes {main} [built]
[./node_modules/url/url.js] 22.8 KiB {main} [built]
[./node_modules/webpack-dev-server/client/index.js?http://localhost] (webpack)-dev-server/client?http://localhost 8.26 KiB {main} [built]
[./node_modules/webpack-dev-server/client/overlay.js] (webpack)-dev-server/client/overlay.js 3.59 KiB {main} [built]
[./node_modules/webpack-dev-server/client/socket.js] (webpack)-dev-server/client/socket.js 1.05 KiB {main} [built]
[./node_modules/webpack-dev-server/node_modules/strip-ansi/index.js] (webpack)-dev-server/node_modules/strip-ansi/index.js 161 bytes {main} [built]
[./node_modules/webpack/hot sync ^\.\/log$] (webpack)/hot sync nonrecursive ^\.\/log$ 170 bytes {main} [built]
[./node_modules/webpack/hot/emitter.js] (webpack)/hot/emitter.js 75 bytes {main} [built]
    + 14 hidden modules
i ｢wdm｣: Compiled successfully.
```

http://localhost:8080/を開く...

![106.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308709/115c9776-2cf9-c840-6360-ec03bcec6c7e.png)

でけた！
長くなったのでここでひとまず切ります。
次回は実践編・・か？何しよう。

## ・・・・・・

チュートリアルすっとばして下記をcloneして実行してみたらこんな感じな奴ができてました。
なんか虫が蠢いてるみたい。。canvasにいろいろ書いてるんすね。
https://github.com/rustwasm/wasm_game_of_life

![1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308709/fbe17912-4a63-7ff2-47d4-22a1707dd518.gif)

ネタ、思いついたかも。