Streaming Instantiation and Fetch
In a real application you do not have WAT source at runtime — you fetch a compiled .wasm binary from a server. The preferred API for this is WebAssembly.instantiateStreaming(), which starts compiling bytes as they arrive over the network rather than waiting for the full download to complete.
instantiateStreaming vs instantiate
Section titled “instantiateStreaming vs instantiate”WebAssembly.instantiate requires the complete byte buffer to be in memory before compilation can begin. For large modules this means the browser sits idle during the download, then pays the full compilation cost in one blocking burst.
WebAssembly.instantiateStreaming feeds bytes to the compiler as they stream in from the network. Compilation and download overlap, so the module is ready sooner — especially noticeable on slow connections or for modules over a few hundred kilobytes.
// instantiate — waits for full download before compilingconst response = await fetch('/module.wasm');const bytes = await response.arrayBuffer();const { instance } = await WebAssembly.instantiate(bytes, {});
// instantiateStreaming — compiles while bytes arriveconst { instance } = await WebAssembly.instantiateStreaming( fetch('/module.wasm'), {});Note that instantiateStreaming accepts the Promise<Response> returned by fetch directly — you do not need to await the fetch first.
The MIME type requirement
Section titled “The MIME type requirement”WebAssembly.instantiateStreaming validates the response’s Content-Type header before it begins streaming bytes to the compiler. The server must serve .wasm files with Content-Type: application/wasm. If it sends any other type — such as application/octet-stream — the API rejects with a TypeError immediately, before any bytes are compiled.
When you cannot control the server’s MIME type configuration, fall back to the two-step pattern:
async function loadWasm(url, imports) { try { return await WebAssembly.instantiateStreaming(fetch(url), imports); } catch (e) { if (e instanceof TypeError) { // MIME type wrong — fall back to arrayBuffer const response = await fetch(url); const bytes = await response.arrayBuffer(); return WebAssembly.instantiate(bytes, imports); } throw e; }}Passing imports
Section titled “Passing imports”The imports object works identically to WebAssembly.instantiate — it is the second argument, and its shape must match the module’s import section exactly.
const result = await WebAssembly.instantiateStreaming( fetch('/module.wasm'), { env: { log: n => console.log(n) } });Caching compiled modules
Section titled “Caching compiled modules”The WebAssembly.Module returned inside result.module is a serialisable compiled artifact. You can store it in IndexedDB so repeat visits skip the compilation step entirely and jump straight to instantiation:
const { module, instance } = await WebAssembly.instantiateStreaming( fetch('/module.wasm'), {});// Store `module` in IndexedDB for next visit// Later: const instance = await WebAssembly.instantiate(cachedModule, {});Run it
Section titled “Run it”The sandbox has no server to fetch from, so fetch() cannot be used here. The runner below uses compileWat() to produce compiled bytes and then calls WebAssembly.instantiate directly — the same path a streaming fallback would follow once it has the bytes.