WebAssembly を Rust でつくり、JavaScript でつかう

こんにちは❗フリーランス・エンジニアの 九保すこひ です。

さてさて、私の開発メインはPHP(Laravel)+ JavaScript(Vue.js)で、もしこれらに不向きな部分があればPythonを使うという形になっています。

実際この3つがあれば(私の)業務的に困ることはほぼないのですが、根っからのプログラム好きですので、「別のテクノロジーもかじっておきたい」欲があったりします。

そこで注目したのが、

Rust言語

です。

なぜ「Rust言語」かというと、ブラウザのJavaScriptを高速化することができる「WebAssembly」をつくることができるからなんですね。

WebAssemblyについては、過去記事がありますのでぜひご覧ください。(前回はC言語を使いました)

📝 参考ページ: 入門!WebAssemblyを試してみた

つまり、Rust言語はウェブ開発に関連させることもできるわけです。

そこで❗

今回はRust言語でWebAssemblyをつくって(ブラウザの)JavaScriptで使えるようにしてみたいと思います。

ぜひ何かの参考になりましたら嬉しいです😊✨

「WebAssemblyは
ゲーム開発でも
使われるらしいですよ」

Rust 言語をインストールする

まずはRust言語のインストールですが、こちらは本家のインストールページ

を参考にしてみてください。(すみません、Linux環境なので・・・💦)

なお、Ubuntuの場合は以下のコマンドを実行すれば自動的に完了します。(途中オプション選択がありますが、defaultのものでOKです)

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Rust開発環境の準備をする

プロジェクトをつくる

コマンドライン(黒い画面のやつです)でRust開発をするためのフォルダに移動し、以下のコマンドを実行してください。

cargo new --lib hello-wasm

※ なお、Cargoとはnpmcomposerのようなパッケージ・マネージャです。私の環境では、rust言語をインストールすると自動的にcargoコマンドが使えるようになっていました 👍

実行すると、hello-wasmフォルダが作成され、中にいろいろと必要なファイルが入っていますが、実際にコーディングするのはsrc/lib.rsです。

※ なお、このファイルには初期状態でサンプルコードが書かれていますが、不要ですので全て消してしまって問題ないです。

Cargoにビルドパッケージをインストールする

WebAssemblyをつくるためのCargoパッケージをインストールします。

cargo install wasm-pack

少し時間はかかりますが、特に途中で何もすることはないです😊✨

コンフィグ設定をする

Cargoプロジェクトの設定ファイルはCargo.tomlというファイルの中に書き込みます。

以下のように変更してください(太文字の部分を追加しました)

Cargo.toml

[package]
name = "hello-wasm"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

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

[dependencies]
wasm-bindgen = "0.2"

WebAssembly 用のコードをつくる

では、実際にRustWebAssembly用のコードをつくってみましょう。

src/lib.rs

use wasm_bindgen::prelude::*;

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

#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("{} さん、こんにちは!", name));
}

中身としてはシンプルに名前をゲットしたらalert()で表示するだけのものです。

Rust をビルドしてWebAssembly をつくる

では、先ほどのコードをWebAssembly化してみましょう。
以下のコマンドを実行してください。

wasm-pack build --target web

これで、pkgフォルダの中にWebAssemblyが作成されているはずです。

JavaScriptで使ってみる

では、作成されたWebAssemblyJavaScriptで使ってみましょう❗

WebAssemblyを設置する

今回は、Laravel内で使う手順ですが、別の環境でも同様になります。

まずは先ほどのpkgフォルダをブラウザからアクセスできる場所に設置します。

つまり、Laravelだとpublicフォルダですね。
今回は「/public/wasm/hello-wasm/pkg」として設置しました。

WebAssembly を使うコードをつくる

では、Laravelに以下のビューを作ります。

resources/views/wasm.blade.php

<html>
<body>
<!-- WebAssembly用のコード -->
<script type="module">

    import init, {greet} from "./wasm/hello-wasm/pkg/hello_wasm.js";

    init()
        .then(() => {

            window.greet = greet;

        });

</script>

<!-- 通常の JavaScript -->
<script>

    window.onload = () => {

        console.log(typeof greet); // ここではまだ読み込まれていない可能性がある

        let timer = setInterval(() => {

            if(typeof greet === 'function') {

                greet("山田太郎");
                clearInterval(timer);

            }

        }, 100)

    };

</script>
</body>
</html>

ここで、少し通常のJavaScriptとは違う部分がでてきています。

<script type="module">

    // 省略

</script>

の部分ですね。

これは私も実際に使ったのは初めてですが、コードの通り「モジュール」を使うコードになります。

つまり、今回の例で言うと、init()WebAssemblyの準備をし、それが完了して初めて Rust 言語で書いたコードが実行できるということになります。

そのため、ページが表示されてすぐ実行しても関数が準備されていない場合があるので、以下の部分でgreet()が関数として使えるかどうかをチェックしているわけです。

if(typeof greet === 'function') { // 👈 ホントに関数なの??をチェック

    // 省略

}

そして、このビューをLaravelのルートに登録すれば完成です。

routes/web.php

Route::get('wasm_test', fn() => view('wasm'));

テストしてみる

では、すぐ終わってしまいますが実際にテストしてみましょう。
http://******/wasm_test」にアクセスします。

はい❗

Rust言語で書いたalert()が実行されました。
成功です😊✨

企業様へのご提案

WebAssemblyを使うと以下のようなメリットがあります。

  • バイナリコードの実行なので高速に処理ができる。(つまり、現在ブラウザでの処理に時間がかかっている部分を高速化できる可能性がある)
  • WebAssembly は一度作っておくと他のシステムにも組み込むことができるので、「使い回し」ができる
  • まだ発展途上のようですが Wasmer という技術を使うとPHPなど様々な言語からも WebAssembly を利用できるようになる(※1)

※1: 参考ページ: Wasmer

もし上記のような機能をご希望でしたら、ぜひお気軽にお問い合わせからご連絡ください。どうぞよろしくお願いいたします。m(_ _)m

おわりに

ということで、今回ははじめて「Rust言語」を使い、WebAssemblyをつくってみました。

なお、実は当初もう一つ注目していた「Go言語」でWebAssemblyを作るつもりでした。

結果としてWebAssembly化するところまで成功したのですが、一点大きなデメリットがあることに気が付きました。

それが、「ファイルサイズ」でした。

Goで作ったWebAssemblyは今回のようなシンプルなコードだけでも2MBぐらいのファイルサイズになってしまいます。

これでは最大の目的「高速化」のために、長いロード時間が発生することになり、「冷たいドリンクを買うために、汗かいて遠くまで歩いていく😂」ような状態になるため、今回は見送ることにしました。

ただ、Goはこれからのメインストリームになるだろうと言われる産業の会社が多く採用してるとのことで(Youtuberでもある酒井潤さんが動画内でおっしゃってました)、また別の部分で注目してみたいと思います。

ぜひ皆さんも試してみてくださいね。

ではでは〜❗


「コーヒー飲むと
気分悪くなるように
なっちゃいました
(飲みすぎ…💦)」

開発のご依頼お待ちしております 😊✨ お問い合わせ
また、こちらもお待ちしております。
  • 実案件の開発サポート: 詳細
  • ツイッターのフォロー: 詳細
どうぞよろしくお願いいたします!
このエントリーをはてなブックマークに追加       follow us in feedly