← レッスン一覧に戻る レッスン 15 / 28
上級 dom
Wasm + フロントエンドフレームワーク
パターン
Wasmは計算処理に、フレームワークはUIに使います:
┌─────────────────┐
│ React/Svelte │ ← UIレンダリング、状態、イベント
│ (JavaScript) │
├─────────────────┤
│ Wasmモジュール │ ← 重い計算処理、データ処理
│ (Rust) │
└─────────────────┘React統合
// hooks/useWasm.ts
import { useState, useEffect } from 'react';
export function useWasm() {
const [wasm, setWasm] = useState(null);
useEffect(() => {
async function load() {
const module = await import('../pkg/my_wasm.js');
await module.default(); // init
setWasm(module);
}
load();
}, []);
return wasm;
}
// components/ImageEditor.tsx
function ImageEditor() {
const wasm = useWasm();
const [processing, setProcessing] = useState(false);
async function applyBlur() {
if (!wasm) return;
setProcessing(true);
const processor = new wasm.ImageProcessor(800, 600);
const imageData = ctx.getImageData(0, 0, 800, 600);
processor.blur(imageData.data, 3);
ctx.putImageData(imageData, 0, 0);
setProcessing(false);
}
return (
<button onClick={applyBlur} disabled={!wasm || processing}>
{processing ? 'Processing...' : 'Apply Blur'}
</button>
);
}Svelte統合
<!-- WasmProcessor.svelte -->
<script lang="ts">
import { onMount } from 'svelte';
let wasm: any = null;
let ready = false;
onMount(async () => {
const module = await import('../pkg/my_wasm.js');
await module.default();
wasm = module;
ready = true;
});
function processData() {
if (!wasm) return;
const result = wasm.process(inputData);
// 結果でUIを更新
}
</script>
{#if ready}
<button on:click={processData}>Process</button>
{:else}
<p>Wasmを読み込み中...</p>
{/if}Vue統合
<!-- WasmComponent.vue -->
<script setup>
import { ref, onMounted } from 'vue';
const wasm = ref(null);
const ready = ref(false);
onMounted(async () => {
const module = await import('../pkg/my_wasm.js');
await module.default();
wasm.value = module;
ready.value = true;
});
function compute() {
if (!wasm.value) return;
const result = wasm.value.heavy_calculation(data);
}
</script>
<template>
<button @click="compute" :disabled="!ready">Compute</button>
</template>Vite設定
// vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
optimizeDeps: {
exclude: ['my-wasm-app'] // Wasmをプリバンドルしない
},
server: {
headers: {
// SharedArrayBufferに必要(オプション)
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
}
}
});Wasmをフレームワークと使うべき場面
| Wasmに適した処理 | JS/フレームワークに残すべき処理 |
|---|---|
| 画像・動画処理 | UIコンポーネント、ルーティング |
| 物理シミュレーション | 状態管理(Reduxなど) |
| 暗号処理 | フォーム処理、バリデーション |
| データパース(CSV、バイナリ) | DOM操作 |
| オーディオ処理 | イベントハンドリング |
| 圧縮・解凍 | HTTPリクエスト(パフォーマンスが重要でない場合) |
経験則: CPU集約的でJavaScriptで10ms以上かかる処理は、Wasmに移行しましょう。
試してみよう
スターターコードは、任意のフレームワークで動作するImageProcessor構造体を示しています。生のピクセルデータを受け取り、Rustで処理します。
試してみる
チャプタークイズ
すべての問題に正解してレッスンを完了しましょう