Load and Instantiate WebAssembly Modules in JavaScript
WebAssembly (Wasm) allows developers to run high-performance code in the browser alongside JavaScript. To use a WebAssembly module, you must first fetch its binary file, compile it, and instantiate it so JavaScript can access its exported functions. This article provides a clear, step-by-step guide on how to load and instantiate WebAssembly modules using modern JavaScript APIs, focusing on both the efficient streaming method and the fallback buffer-based method.
The Modern Approach: Streaming Instantiation
The most efficient way to load and instantiate a WebAssembly module
is by using the WebAssembly.instantiateStreaming() API.
This method compiles and instantiates the module on the fly as the
.wasm file is being downloaded over the network, which
significantly reduces startup time.
Syntax and Example
To use streaming instantiation, you pass a fetched response promise
directly to WebAssembly.instantiateStreaming(), along with
an optional import object.
// Define imports (functions, memory, etc.) that the Wasm module needs from JavaScript
const importObject = {
env: {
log: (arg) => console.log(arg)
}
};
// Fetch, compile, and instantiate the Wasm file in a single streaming operation
WebAssembly.instantiateStreaming(fetch('module.wasm'), importObject)
.then(obj => {
// Access the exported functions from the Wasm instance
const result = obj.instance.exports.add(5, 10);
console.log(result); // Outputs the result of the Wasm function
})
.catch(error => {
console.error("Failed to load and instantiate Wasm:", error);
});Using async/await, the same process looks like this:
async function loadWasm() {
try {
const importObject = {};
const obj = await WebAssembly.instantiateStreaming(fetch('module.wasm'), importObject);
// Call an exported function
obj.instance.exports.myFunction();
} catch (error) {
console.error("Error loading WebAssembly:", error);
}
}
loadWasm();Note: For instantiateStreaming() to work, the server
serving the .wasm file must return the correct MIME type:
application/wasm.
The Fallback Approach: ArrayBuffer Instantiation
If the server does not support the application/wasm MIME
type, or if you are running the code in an environment where
instantiateStreaming is not available, you must fallback to
loading the file as an ArrayBuffer and then compiling
it.
This process involves downloading the entire file first, converting it into a typed array of bytes, and then instantiating those bytes.
Syntax and Example
async function loadWasmFallback() {
try {
const response = await fetch('module.wasm');
const bytes = await response.arrayBuffer();
// Instantiate using the byte array
const obj = await WebAssembly.instantiate(bytes);
// Access the exported functions
obj.instance.exports.myFunction();
} catch (error) {
console.error("Fallback WebAssembly instantiation failed:", error);
}
}
loadWasmFallback();Understanding the Components
Whether you use streaming or fallback compilation, the instantiation process involves the same key components:
- The
importObject(Optional): This is a JavaScript object containing values, functions, or memory spaces that you want to pass into your WebAssembly module. Wasm modules can call these JavaScript functions during execution. - The Result Object: The resolved promise returns a
JavaScript object containing two properties:
module: AWebAssembly.Moduleobject that can be cached or shared with web workers.instance: AWebAssembly.Instanceobject that contains all the exported WebAssembly functions insideinstance.exports.