WEBエンジニア勉強会 #13 (東京都, 渋谷)にて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
:
(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
っていうプロジェクト名にします。
構造はこんな感じ。
wasm-game-of-life/
├── Cargo.toml
├── LICENSE_APACHE
├── LICENSE_MIT
├── README.md
└── src
├── lib.rs
└── utils.rs
src/lib.rsっていうのがスクリプトの本体で、単にjsのalertを実行するだけっぽいです。
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ディレクトリというのが作られました。
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ディレクトリができました。
www/
├── bootstrap.js
├── index.html
├── index.js
├── LICENSE-APACHE
├── LICENSE-MIT
├── package.json
├── README.md
└── webpack.config.js
ちなみに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フォルダで以下を。
$ 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します。
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.
でけた!
長くなったのでここでひとまず切ります。
次回は実践編・・か?何しよう。
・・・・・・
チュートリアルすっとばして下記をcloneして実行してみたらこんな感じな奴ができてました。
なんか虫が蠢いてるみたい。。canvasにいろいろ書いてるんすね。
https://github.com/rustwasm/wasm_game_of_life
ネタ、思いついたかも。