This directory contains example WebAssembly modules demonstrating how to build and use WASM with WasmWorker.
rust-add - Basic Rust WASM Module
A simple Rust module demonstrating basic arithmetic operations and recursive functions.
Functions:
add(a: i32, b: i32) -> i32- Add two numberssubtract(a: i32, b: i32) -> i32- Subtract two numbersmultiply(a: i32, b: i32) -> i32- Multiply two numbersdouble(x: i32) -> i32- Double a numberfib(n: u32) -> u64- Calculate Fibonacci number (recursive)
- Rust toolchain - Install from https://rustup.rs/
- wasm32 target - Add with:
rustup target add wasm32-unknown-unknown - Node.js >= 20.0.0 (for running the demo)
- pnpm >= 8.0.0
# Navigate to the example
cd examples/rust-add
# Build the WASM module
./build.sh
# Verify the output
ls -lh dist/module.wasmThis will compile the Rust code to WebAssembly and output dist/module.wasm.
From the repository root:
# Make sure dependencies are installed
pnpm install
# Build the SDK
pnpm build
# Start the demo
pnpm demoThe demo will open at http://localhost:3000 and automatically load the rust-add example module.
import { WasmWorker } from '@wasmworker/sdk';
// Load the WASM module
const worker = await WasmWorker.load({
moduleUrl: '/examples/rust-add/dist/module.wasm'
});
// Call functions
const sum = await worker.call<{ a: number; b: number }, number>('add', {
a: 10,
b: 20
});
console.log(`10 + 20 = ${sum}`); // 10 + 20 = 30
// Clean up
worker.terminate();mkdir examples/my-example
cd examples/my-example# Cargo.toml
[package]
name = "my-example"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[profile.release]
opt-level = "z" # Optimize for size
lto = true # Enable link-time optimization// src/lib.rs
#[no_mangle]
pub extern "C" fn my_function(x: i32) -> i32 {
x * 2
}#!/bin/bash
# build.sh
set -e
echo "Building WASM module..."
mkdir -p dist
cargo build --target wasm32-unknown-unknown --release
cp target/wasm32-unknown-unknown/release/my_example.wasm dist/module.wasm
SIZE=$(wc -c < dist/module.wasm | tr -d ' ')
echo "Built module.wasm (${SIZE} bytes)"Make it executable:
chmod +x build.sh./build.sh#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
a + b
}Usage:
const result = await worker.call('add', { a: 5, b: 3 });
// result = 8#[no_mangle]
pub extern "C" fn square(x: i32) -> i32 {
x * x
}Usage:
const result = await worker.call('square', 5);
// result = 25#[no_mangle]
pub extern "C" fn fibonacci(n: u32) -> u64 {
if n <= 1 {
return n as u64;
}
fibonacci(n - 1) + fibonacci(n - 2)
}Usage:
// Runs in worker - doesn't block UI!
const result = await worker.call('fibonacci', 40);
console.log(`fib(40) = ${result}`);For passing complex data structures or buffers, you'll need to work with WASM linear memory:
use std::slice;
#[no_mangle]
pub extern "C" fn sum_array(ptr: *const i32, len: usize) -> i32 {
let numbers = unsafe { slice::from_raw_parts(ptr, len) };
numbers.iter().sum()
}
#[no_mangle]
pub extern "C" fn alloc(size: usize) -> *mut u8 {
let mut buf = Vec::with_capacity(size);
let ptr = buf.as_mut_ptr();
std::mem::forget(buf);
ptr
}
#[no_mangle]
pub extern "C" fn dealloc(ptr: *mut u8, size: usize) {
unsafe {
Vec::from_raw_parts(ptr, size, size);
}
}In Cargo.toml:
[profile.release]
opt-level = "z" # Optimize for size
lto = true # Link-time optimization
codegen-units = 1 # Better optimization
strip = true # Strip debug symbols
panic = "abort" # Smaller panic handlerInstall binaryen:
# macOS
brew install binaryen
# Ubuntu/Debian
apt-get install binaryenUpdate build.sh:
#!/bin/bash
set -e
cargo build --target wasm32-unknown-unknown --release
wasm-opt -Oz -o dist/module.wasm \
target/wasm32-unknown-unknown/release/my_example.wasm
echo "Optimized: $(wc -c < dist/module.wasm) bytes"Add to Cargo.toml:
[profile.release]
panic = "abort"
[profile.release.package."*"]
opt-level = "z"#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add() {
assert_eq!(add(2, 3), 5);
}
}Run tests:
cargo testCreate test.mjs:
import { WasmWorker } from '@wasmworker/sdk';
const worker = await WasmWorker.load({
moduleUrl: './dist/module.wasm'
});
console.log('Testing add...');
const sum = await worker.call('add', { a: 2, b: 3 });
console.assert(sum === 5, 'add(2, 3) should equal 5');
console.log('All tests passed!');
worker.terminate();Run with Node.js:
node test.mjswasm-objdump -x dist/module.wasm | grep "export"wasm-validate dist/module.wasmwasm2wat dist/module.wasm -o module.watWhile these examples use Rust, WasmWorker supports WASM modules compiled from any language:
- Rust - Excellent WASM support, zero runtime
- C/C++ - Use Emscripten or WASI SDK
- Go - Use TinyGo for smaller binaries
- AssemblyScript - TypeScript-like syntax for WASM
- Zig - Modern systems language with great WASM support
rustup target add wasm32-unknown-unknown- Enable size optimizations in
Cargo.toml - Use
wasm-opt -Oz - Remove unused dependencies
- Use
cargo treeto audit dependencies
Check the browser console for detailed error messages from the WasmWorker runtime.
Ensure your function is:
- Marked with
#[no_mangle] - Declared as
pub extern "C" - Actually compiled (check with
wasm-objdump)
We welcome contributions of new examples! Please:
- Follow the existing structure
- Include a README.md in your example directory
- Add build and clean scripts
- Test thoroughly
- Update this main examples README
See CONTRIBUTING.md for more details.