← Back to Lessons Lesson 15 of 28
Advanced dom
Wasm + Frontend Frameworks
The Pattern
Use Wasm for computation, your framework for UI:
┌─────────────────┐
│ React/Svelte │ ← UI rendering, state, events
│ (JavaScript) │
├─────────────────┤
│ Wasm Module │ ← Heavy computation, data processing
│ (Rust) │
└─────────────────┘React Integration
// 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 Integration
<!-- 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);
// update UI with result
}
</script>
{#if ready}
<button on:click={processData}>Process</button>
{:else}
<p>Loading Wasm...</p>
{/if}Vue Integration
<!-- 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 Configuration
// vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
optimizeDeps: {
exclude: ['my-wasm-app'] // Don't pre-bundle Wasm
},
server: {
headers: {
// Required for SharedArrayBuffer (optional)
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
}
}
});When to Use Wasm with a Framework
| Use Wasm for | Keep in JS/Framework |
|---|---|
| Image/video processing | UI components, routing |
| Physics simulation | State management (Redux, etc.) |
| Cryptography | Form handling, validation |
| Data parsing (CSV, binary) | DOM manipulation |
| Audio processing | Event handling |
| Compression/decompression | HTTP requests (unless perf-critical) |
Rule of thumb: If it's CPU-bound and takes >10ms in JavaScript, move it to Wasm.
Try It
The starter code shows an ImageProcessor struct that works with any framework — it accepts raw pixel data and processes it in Rust.
Try It
Chapter Quiz
Pass all questions to complete this lesson