Early Beta — The Web SDK is in early beta. APIs may change between releases.
Package Installation
The Web SDK is split into three packages. Install all three to access every feature, or pick only the backends you need:Package Breakdown
If you only need LLM text generation, you can skip
@runanywhere/web-onnx. If you only need
STT/TTS/VAD, you can skip @runanywhere/web-llamacpp. The core @runanywhere/web package is
always required.Bundler Configuration
Vite (Recommended)
The starter app uses Vite. Here is the completevite.config.ts that handles WASM serving, Cross-Origin Isolation, Web Workers, and production builds:
vite.config.ts
Webpack
webpack.config.js
Next.js
next.config.js
Cross-Origin Isolation Headers
For multi-threaded WASM (significantly better performance), your server must set two HTTP headers:SharedArrayBuffer, which is required for multi-threaded WASM. Without them, the SDK falls back to single-threaded mode.
Server Configuration
- Vercel
- Netlify
- Cloudflare Pages
- Nginx
- Apache
vercel.json
Package Contents
@runanywhere/web-llamacpp
@runanywhere/web-onnx
The sherpa-onnx WASM module is only loaded when you call
ONNX.register(). If you only need LLM
text generation, you don’t need @runanywhere/web-onnx at all.Supported Model Formats
Browser Compatibility
Troubleshooting
”SharedArrayBuffer is not defined”
Cause: Missing Cross-Origin Isolation headers. Fix: Add the COOP/COEP headers to your server configuration. The SDK will still work in single-threaded mode without them, but performance will be reduced.WASM file not loading
Cause: Bundler not configured correctly, oroptimizeDeps.exclude missing for Vite.
Fix: For Vite, ensure @runanywhere/web-llamacpp and @runanywhere/web-onnx are in optimizeDeps.exclude. For other bundlers, configure .wasm as static assets.
WASM loads HTML instead of binary (production)
Cause: Your server has a SPA catch-all route (e.g., Expressapp.get('*', (req, res) => res.sendFile('index.html'))) that serves HTML for any unmatched path, including .wasm file requests. The WASM compiler then receives HTML bytes (3c 21 44 4f = <!DO…) instead of the binary, causing a cryptic error.
Error message: CompileError: WebAssembly.instantiate(): expected magic word 00 61 73 6d, found 3c 21 44 4f
Fix: Ensure your server serves .wasm files with the correct MIME type before the SPA catch-all. For Express:
VLM Worker fails with “non-JavaScript MIME type”
Cause: The VLM Web Worker script URL resolves to a path that returns HTML (same catch-all issue as above), or Vite’s?worker&url import isn’t configured correctly.
Error message: Failed to load module script: The server responded with a non-JavaScript MIME type of "text/html"
Fix:
- Ensure
worker: { format: 'es' }is in your Vite config - Ensure the catch-all route doesn’t intercept
.jsfile requests (see fix above) - For the
?worker&urlimport, add a TypeScript declaration:
OPFS storage not persisting
Cause: Incognito/Private mode or browser eviction. Fix: Ensure you are not in private browsing mode. Safari has known OPFS issues — Chrome/Edge is recommended.Large model download crashes the tab
Cause: Downloading models larger than ~200MB can exhaust available browser memory, especially on memory-constrained devices or when other tabs are open. The OPFS write operation buffers the entire model before committing. Fix:- Close other browser tabs to free memory before downloading large models
- Start with smaller models (350M-500M parameter models are typically under 300MB)
- Monitor
model.downloadProgressevents to detect stalls - If the tab crashes during download, refresh and retry — OPFS supports resuming from partial downloads
WebGPU WASM 404 in console
Cause: The SDK tries to loadracommons-llamacpp-webgpu.wasm for GPU acceleration but it may not be available.
Fix: This is harmless. The SDK gracefully falls back to CPU mode. You can suppress the 404 by ensuring the WebGPU WASM files are copied to your assets directory.
Next Steps
Quick Start
Initialize the SDK and run your first browser inference