TrustformeRS WebAssembly
WebAssembly bindings for the TrustformeRS transformer library, enabling transformer models to run directly in web browsers and Node.js environments with WebGPU hardware acceleration.
Version: 0.2.0 | Status: Stable | Tests: ~130 | SLoC: 55,721 | Last Updated: 2026-07-02
Features
- WebGPU Backend: GPU compute via direct
web-sys/js-sysbindings to the browser WebGPU API (nowgpucrate dependency), with automatic CPU fallback — see "WebGPU Notes" below for current dispatch-path coverage - Web Workers Parallelism: Multi-threaded inference via SharedArrayBuffer
- IndexedDB Caching: Persistent model and KV-cache storage in the browser
- BERT WASM Model: Complete BERT implementation running in-browser
- React/Vue/Angular/Web Components: First-class framework bindings
- Streaming Inference: Token-by-token generation with streaming API
- SIMD Support: Hardware-accelerated tensor ops where available
- Mobile Optimization: Battery-aware, network-adaptive loading
Building
Prerequisites
- Rust (latest stable)
- wasm-pack (
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh)
Build Commands
# Build for all targets
# Or build individually:
Usage
Browser (Direct)
Node.js
const = require;
const tf = ;
const tensor = ;
console.log;
Webpack/Bundler
import * as wasm from './pkg-bundler/trustformers_wasm';
API Overview
This crate exposes roughly 2,276 public items (functions, structs, enums, and traits, including trait/impl-block methods) across 102 source files under src/; about 621 of those are top-level module-level declarations.
Core Classes
TrustformersWasm
Main entry point for the library.
const tf = ;
console.log; // "0.2.0"
console.log; // true
WasmTensor
Core tensor operations.
// Creation
const a = ;
const b = ;
const c = ;
const d = ;
// Operations
const sum = a.;
const prod = a.;
const transposed = a.;
// Activations
const relu_out = a.;
const gelu_out = a.;
const softmax_out = a.;
Linear
Fully connected layer.
const linear = ;
const output = linear.;
BertModelWasm
BERT model running entirely in WASM.
const config = ;
const model = ;
const output = model.;
WebGPU Backend
import from './pkg-web/trustformers_wasm.js';
// Check whether the browser exposes navigator.gpu at all
console.log;
// create_tensor() tries WebGPU first and falls back to CPU automatically
// (see "WebGPU Notes" below for current dispatch-path coverage)
const a = await ;
const b = await ;
const sum = await a.;
console.log;
Framework Bindings
React
import from 'trustformers-react';
Vue
import from 'trustformers-vue';
export default
Angular
import { TrustformersService } from 'trustformers-angular';
@Injectable({ providedIn: 'root' })
export class AppComponent {
constructor(private tf: TrustformersService) {}
async generate(prompt: string) {
return this.tf.generate(prompt).pipe(toArray()).toPromise();
}
}
Web Components
Utilities
// Performance measurement
const timer = ;
// ... do work ...
console.log;
// Memory statistics
const stats = ;
console.log;
// Feature detection
console.log;
console.log;
Feature Flags
webgpu— WebGPU compute backend via directweb-sys/js-sysbindings to the browser API (nowgpucrate dependency); gatescompute::webgpu,compute::gpu_tensor,compute::webgpu_simpleweb-workers— Web Workers-based multi-threaded execution (src/compute/web_workers.rs)shared-memory— SharedArrayBuffer-backed cross-thread shared memory (src/compute/threads.rs)kernel-fusion— Fused transformer kernel patterns (MHA, FFN, LayerNorm+Residual, RMSNorm, SwiGLU) incompute/webgpu/kernel_fusion.rs+advanced_fusion_patterns.rs; note these modules currently compile wheneverwebgpuis enabled, so this flag is not yet an independent source-level gateasync-executor— Async task executor for WebGPU dispatch (compute/webgpu/async_executor.rs); likekernel-fusion, currently compiles underwebgpuregardless of this flagindexeddb— IndexedDB model/KV-cache persistence; also gates the top-levelstoragemodule itself, somemory64/streaming-loader/model-splittingbelow need this enabled toomemory64— WASM memory64 addressing for models >4GB (src/storage/memory64.rs)streaming-loader— Progressive chunked model loading (src/storage/streaming_loader.rs,progressive_loader.rs)model-splitting— Splits large models into chunks for loading (src/storage/model_splitting.rs)react-components— React hooks and component library (src/react_components.rs)vue-components— Vue composables and plugin (src/vue_components.rs)angular-components— Angular services and directives (src/angular_components.rs)web-components— Framework-agnostic custom elements (src/web_components/)playground— Interactive browser playground (src/playground.rs)streaming-generation— Token-by-token streaming inference (src/streaming_generation.rs)mobile-optimization— Battery/network-adaptive loading, touch gestures, camera integration, device-capability detection (src/mobile.rs,touch_gestures.rs,camera_integration.rs,device_capability*)console_panic— Routes Rust panics to the browser console viaconsole_error_panic_hook(part ofdefault)dlmalloc-alloc— Swaps the global allocator todlmalloc(src/allocator.rs) for wasm32 (part ofdefault)default—console_panic+dlmalloc-allocsize-optimized— Same composition asdefaulttoday (dlmalloc-alloc+console_panic)performance-optimized—dlmalloc-alloc+kernel-fusion+async-executor; does not includewebgpuitself, so the fusion/executor code (gated behindwebgpuat the module level) won't actually compile in unlesswebgpuis enabled toominimal— Smallest viable build:dlmalloc-alloconlyfull— Enables every additive feature exceptwebgpuandconsole_panic(web-workers, shared-memory, kernel-fusion, async-executor, indexeddb, memory64, streaming-loader, model-splitting, react-components, vue-components, angular-components, web-components, playground, streaming-generation, mobile-optimization, dlmalloc-alloc); combine with--features full,webgpufor GPU support too
WebGPU Notes
This crate has no dependency on the native wgpu crate. WebGPU support is implemented by calling the browser's WebGPU API directly through hand-written web-sys/js-sys bindings:
- Types:
GpuAdapter,GpuDevice,GpuQueue, etc. arejs_sys::Objectaliases (src/compute/webgpu/types.rs), with extension traits (GpuDeviceExt,GpuAdapterExt,GpuQueueExt,GpuBufferExt) that use JS reflection for methods web-sys doesn't bind natively. - Device negotiation:
navigator.gpu→requestAdapter()→requestDevice(), each awaited viawasm_bindgen_futures::JsFuturewith explicit null/undefined checks (GpuTensor::init_webgpuinsrc/compute/gpu_tensor.rs;WebGPUOps::initializeinsrc/compute/webgpu_simple.rs). - Shared backend handle: the negotiated backend is wrapped in
Rc<RefCell<WebGPUBackend>>(src/compute/gpu_tensor.rs) for cheap sharing across derived tensors plus interior mutability for pipeline caching;RefCellborrows are scoped so none is ever held across an.await. - CPU fallback is real at multiple levels:
WebGPUBackend::is_available()probes fornavigator.gpubefore attempting GPU init;GpuTensorFactory::create_tensorfalls back silently on any initialization error; per-op methods onGpuTensor(matmul/add/relu) route to CPU tensor math whenever no GPU backend is active. - Two dispatch paths of different completeness coexist — know which one you're using:
WebGPUOps(src/compute/webgpu_simple.rs) is fully wired end-to-end: it compiles 7 real WGSL compute shaders (matmul, add, relu, sigmoid, tanh, gelu, softmax), builds storage buffers/bind groups/command encoders, dispatches compute passes, and reads results back via a staging buffer +map_async/getMappedRange.WebGPUBackend/SimpleGpuOps(src/compute/webgpu/backend.rs,simple_ops.rs) — the path behind theRc<RefCell>-wrappedGpuTensor— allocate real GPU buffers and pipelines, but their dispatch methods (dispatch_add/dispatch_relu/dispatch_matmul, andSimpleGpuOps::matmul/softmax/layer_norm/attention) currently execute the CPU fallback path by explicit documented design; GPU dispatch for these ops isn't wired in yet.- Recommendation: use
WebGPUOpsdirectly if you need guaranteed end-to-end GPU execution today;GpuTensoris convenient but currently CPU-backed for most ops even when a GPU device was successfully acquired.
Examples
See the examples/ directory for complete examples:
index.html/playground.html— Interactive browser demodemo/— Full-featured playground application- Node.js example in
examples/
Performance Tips
- Enable WebGPU: Use Chrome 113+ / Edge 113+ for 50-100x speedup
- Enable SIMD: Compile with WASM SIMD128 target feature
- Batch operations: Process multiple inputs together
- Use IndexedDB caching: Avoid re-downloading models between sessions
- Enable kernel fusion:
webgpu+kernel-fusionfeatures - Reuse tensors: Minimize allocations in hot loops
Testing
This crate has two distinct test layers:
- Rust unit tests — in-source tests use plain
#[test]attributes (163 occurrences across 39 files; 0#[wasm_bindgen_test], despitewasm-bindgen-testbeing a dev-dependency), so they compile and run as ordinary host-target Rust tests; no browser orwasm-packrunner is required for this layer. - Browser/E2E tests — a separate JS-driven suite under
tests/*.js(Playwright + Jest: cross-browser, e2e, performance, visual-regression, memory-leak checks), run vianpm test/npx playwright testfromtests/package.json, independent of the Rust test binary.
# Run the Rust unit tests (host target)
# Run with specific features
# Check that the actual wasm32 build compiles
# Run the browser/E2E JS suite
&& &&
~130 unit tests with 100% pass rate for this crate, covering:
- Core tensor operations
- WebGPU backend (mock device)
- BERT forward pass
- Framework binding contracts
- Streaming generation
- IndexedDB model cache
Workspace-wide (cargo nextest run --workspace --all-features, 2026-07-01): 18,102 passed / 0 failed / 119 skipped; 0 clippy warnings; 0 rustdoc warnings.
Limitations
- WebGPU requires Chrome 113+, Edge 113+, or Safari (experimental)
- SharedArrayBuffer requires cross-origin isolation headers
- SIMD requires WASM SIMD128 browser support
- Memory typically capped at 2-4GB (use
memory64+ quantization for large models) WebGPUBackend/SimpleGpuOps(the dispatch path behindGpuTensor) currently execute the CPU fallback for matmul/add/relu/softmax/layer_norm/attention by documented design — useWebGPUOps(compute::webgpu_simple) directly for guaranteed end-to-end GPU dispatch today (see "WebGPU Notes")- 0
todo!()/unimplemented!()macros in source, but several documented simplifications remain (none block compilation or panic): a no-op cache-clear recovery action (src/error.rs), fixed-bytes-per-element quantization stats (src/optimization/quantization/quantizer.rs), hardcoded device-capability probes (src/device_capability/detector.rs), fixed-constant (non-bit-width-aware) basic quantization math (src/optimization/quantization/algorithms/basic.rs), synthesizedblob:/data:URLs in place ofURL.createObjectURL()(src/storage/model_splitting.rs,src/compute/threads.rs), and default (non-queried) device capabilities (src/compute/webgpu/mod.rs)
License
Apache-2.0