unwasm: Universal WebAssembly Tools
unwasm provides a suite of universal WebAssembly (Wasm) tools for JavaScript, designed to simplify the integration of `.wasm` modules across various JavaScript runtimes, frameworks, and build environments. It currently stands at version 0.5.3, with a release cadence that includes frequent patch and minor updates. The project's core mission is to align with the WebAssembly/ES Module Integration proposal while maintaining broad compatibility with existing ecosystem libraries. Its key differentiators include automated resolution of WebAssembly imports, dynamic generation of code bindings tailored for bundlers, and a flexible API supporting both static and dynamic `.wasm` module imports. This includes explicit support for import objects and direct `WebAssembly.Module` instances via a `?module` suffix, catering to environments both with and without top-level `await` capabilities.
Common errors
-
TypeError: require is not a function in ES module scope
cause Attempting to use CommonJS `require()` to import `unwasm` or `.wasm` files after v0.4.0, which transitioned to an ESM-only distribution.fixSwitch to ES module `import` syntax. For example, `import { Name } from 'pkg'` instead of `const Name = require('pkg');` -
TypeError: rand is not a function / Cannot read properties of undefined (reading 'call')
cause Calling a named WebAssembly export (e.g., `rand`) from a statically imported module before its required 'init' function has been called and awaited with the necessary import object.fixEnsure the default 'init' function (e.g., `initRand`) for the `.wasm` module is called and awaited with its import object before attempting to use any of its named exports.
Warnings
- breaking unwasm transitioned to an ESM-only distribution. CommonJS (require()) syntax for importing unwasm or any .wasm files processed by unwasm is no longer supported.
- gotcha When using static imports for WebAssembly modules that require an import object, named exports will be proxied. They will only become callable after the default 'init' function (e.g., `initRand`) has been called and awaited with the necessary import object.
- breaking The behavior for WebAssembly module instantiation changed with the introduction of 'auto fallback to module mode'. This might alter how some environments or existing configurations handle module instantiation if they previously relied on specific manual handling of different modes.
Install
-
npm install unwasm -
yarn add unwasm -
pnpm add unwasm
Imports
- sum
const { sum } = require('unwasm/examples/sum.wasm');import { sum } from 'unwasm/examples/sum.wasm'; - initRand, rand
import { rand } from 'unwasm/examples/rand.wasm'; const randomNumber = rand();import initRand, { rand } from 'unwasm/examples/rand.wasm'; // ... await initRand({ env: { seed: () => () => Math.random() * Date.now() } }); - _sumMod
import { _sumMod } from 'unwasm/examples/sum.wasm?module';import _sumMod from 'unwasm/examples/sum.wasm?module';
Quickstart
import initRand, { rand } from "unwasm/examples/rand.wasm";
// This quickstart assumes unwasm's build-time integration is configured
// to process '.wasm' imports, e.g., through a Vite or Rollup plugin.
async function runWasmExample() {
// Initialize the WebAssembly module that requires an import object.
// This example provides a 'seed' function for the 'env' namespace.
await initRand({
env: {
seed: () => () => Math.random() * Date.now()
}
});
// Now the 'rand' function (exported from rand.wasm) can be called.
const randomNumber = rand();
console.log("Generated random number from WASM module:", randomNumber);
// Demonstrate dynamic import for a simpler module without explicit initialization.
const { sum } = await import("unwasm/examples/sum.wasm");
const result = sum(10, 20);
console.log("Result of sum(10, 20) from WASM module:", result);
}
runWasmExample();