**WebAssembly(Wasm)**は、ブラウザ上で高性能なコードを実行するためのバイナリフォーマットで、Rustのようなシステムプログラミング言語と相性が非常に良い技術です。
WebAssemblyを使えば、Rustで書いたコードをブラウザ上で動かすことができ、パフォーマンスの高いWebアプリケーションを構築することができます。
この記事では、RustをWebAssemblyにコンパイルして、ブラウザで実行する基本的な手順を学びます。
WebAssemblyとRustの基礎
**WebAssembly(Wasm)**は、CやRustなどの低レベル言語をブラウザ上で実行するために設計されたバイナリフォーマットです。
これにより、JavaScriptでは得られないネイティブに近いパフォーマンスを提供します。
Rustは、メモリ管理やコンパイラの最適化が優れているため、WebAssemblyとの統合に適しています。
WebAssemblyの特徴
- 高速: WebAssemblyは、ブラウザでの実行に最適化されており、高速なパフォーマンスを実現します。
- クロスプラットフォーム: すべての主要なブラウザ(Chrome, Firefox, Safari, Edge)がWebAssemblyをサポートしており、プラットフォームに依存しません。
- 安全性: WebAssemblyはサンドボックス内で実行されるため、外部の脅威から守られます。
RustとWebAssemblyの環境構築
RustでWebAssemblyを利用するためには、いくつかのツールをインストールして準備を行う必要があります。
RustのWasmターゲットのインストール
まず、RustにWebAssemblyターゲットを追加します。
これは、RustのコードをWebAssemblyにコンパイルするためのものです。
$ rustup target add wasm32-unknown-unknown
このコマンドで、wasm32-unknown-unknown
というターゲットをRustに追加し、WebAssembly向けにコンパイルできるようになります。
wasm-pack
のインストール
次に、RustからWebAssemblyをビルドするためのツール wasm-pack
をインストールします。
wasm-pack
は、RustのプロジェクトをWebAssemblyに変換し、ブラウザやNode.jsで使えるようにパッケージ化します。
$ cargo install wasm-pack
npm
の準備
WebAssemblyをブラウザ上で動かすためには、npm(Node.jsのパッケージ管理ツール)が必要です。
npm
を使ってJavaScriptとWebAssemblyを連携させるパッケージを管理します。
RustプロジェクトをWebAssemblyに変換
次に、RustのプロジェクトをWebAssemblyに変換する手順を説明します。
Rustプロジェクトの作成
まず、新しいRustプロジェクトを作成します。
$ cargo new wasm_example --lib
$ cd wasm_example
このプロジェクトは、ライブラリとしてRustの関数を定義し、それをWebAssemblyとしてエクスポートする構成です。
WebAssembly用コードの記述
RustのコードをWebAssembly向けにエクスポートします。
Rustの関数をWebAssemblyで使用できるようにするには、wasm-bindgen
クレートを使います。
Cargo.toml
の設定
まず、Cargo.toml
に wasm-bindgen
の依存を追加します。
[dependencies]
wasm-bindgen = "0.2"
Rustコードの実装
次に、src/lib.rs
にRustのコードを実装します。
use wasm_bindgen::prelude::*;
// WebAssemblyにエクスポートする関数
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
format!("こんにちは、{}!", name)
}
#[wasm_bindgen]
属性を使うことで、この関数はWebAssemblyとしてエクスポートされ、JavaScriptから呼び出すことができるようになります。
WebAssemblyのビルド
次に、wasm-pack
を使ってプロジェクトをWebAssemblyにビルドします。
$ wasm-pack build --target web
このコマンドを実行すると、pkg
というディレクトリが生成され、その中にWebAssemblyバイナリ(.wasm
ファイル)とJavaScriptのラッパーが含まれています。
ブラウザでWebAssemblyを実行
WebAssemblyをブラウザで実行するためのHTMLとJavaScriptのコードを用意します。
HTMLファイルの作成
次に、プロジェクトルートに index.html
を作成し、WebAssemblyを実行するための基本的なHTMLファイルを用意します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RustとWebAssembly</title>
</head>
<body>
<h1>Rust + WebAssembly Example</h1>
<input type="text" id="name-input" placeholder="名前を入力">
<button id="greet-button">挨拶</button>
<p id="greet-result"></p>
<script type="module">
import init, { greet } from './pkg/wasm_example.js';
async function run() {
await init();
const button = document.getElementById('greet-button');
button.addEventListener('click', () => {
const name = document.getElementById('name-input').value;
const result = greet(name);
document.getElementById('greet-result').textContent = result;
});
}
run();
</script>
</body>
</html>
ローカルサーバーの起動
ブラウザでWebAssemblyを実行するために、ローカルサーバーを起動します。
ここでは、npm
を使って簡単なHTTPサーバーをセットアップします。
$ npm install -g serve
$ serve .
このコマンドでローカルサーバーが起動し、ブラウザで index.html
を開いてWebAssemblyを実行できます。
実践的なWebAssemblyの活用
WebAssemblyは、パフォーマンスが要求されるWebアプリケーションで非常に有用です。
例えば、画像処理や暗号化処理など、計算量の多い処理をWebAssemblyで行い、ブラウザ上で高速に実行することが可能です。
画像処理の例
Rustで画像フィルタをWebAssemblyを通してブラウザで実行することもできます。
以下はその簡単な例です。
use wasm_bindgen::prelude::*;
use image::GenericImageView;
#[wasm_bindgen]
pub fn grayscale(image_data: &[u8]) -> Vec<u8> {
let img = image::load_from_memory(image_data).unwrap();
let mut grayscale_img = img.to_luma8();
grayscale_img.into_raw()
}
これにより、ブラウザ上で画像データを読み込み、Rustで画像処理を行い、WebAssemblyを通して結果を表示することが可能です。
練習問題
練習問題1: WebAssemblyとRustの連携
次の手順に従って、RustとWebAssemblyを使った簡単なWebアプリケーションを作成してください。
- 新しいRustプロジェクトを作成し、
wasm-bindgen
を追加します。 - Rustで計算処理(例:フィボナッチ数列)を実装し、WebAssemblyとしてエクスポートします。
- ブラウザで結果を表示できるように、HTMLとJavaScriptのファイルを作成してください。
まとめ
今回の記事では、RustとWebAssemblyを使ってブラウザ上でRustのコードを実行する方法を学びました。
WebAssemblyは、Webアプリケーションで高パフォーマンスを発揮するための強力なツールです。
Rustとの相性が非常に良く、Webアプリケーションのパフォーマンスを最適化するために広く利用されています。