GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — GitHub - unjs/unwasm: 🇼 WebAssembly tools for JavaScript

BranchesTags
Open more actions menu

Latest commit

 

History

166 Commits
166 Commits

Folders and files

NameName
Last commit message
Last commit date
.github/workflows
.github/workflows
 
 
examples
examples
 
 
src
src
 
 
test
test
 
 
.editorconfig
.editorconfig
 
 
.gitignore
.gitignore
 
 
.oxfmtrc.json
.oxfmtrc.json
 
 
.oxlintrc.json
.oxlintrc.json
 
 
CHANGELOG.md
CHANGELOG.md
 
 
LICENSE
LICENSE
 
 
README.md
README.md
 
 
build.config.ts
build.config.ts
 
 
package.json
package.json
 
 
plugin.d.ts
plugin.d.ts
 
 
pnpm-lock.yaml
pnpm-lock.yaml
 
 
pnpm-workspace.yaml
pnpm-workspace.yaml
 
 
renovate.json
renovate.json
 
 
tsconfig.json
tsconfig.json
 
 
vitest.config.ts
vitest.config.ts
 
 

Repository files navigation

unwasm

npm version npm downloads codecov

Universal WebAssembly tools for JavaScript.

unwasm lets you import a .wasm file the same way you import any other module. It reads the module at build time, works out what it imports and exports, and generates the right bindings for your bundler.

import { sum } from "sum.wasm";

Goal

unwasm aims to be a common, future-proof way to support WebAssembly modules across JavaScript runtimes, frameworks, and build tools. It follows the WebAssembly Community Group's ES Module Integration proposal as closely as possible, while staying compatible with today's ecosystem libraries.

Bindings API

When you import a .wasm module, unwasm resolves, reads, and parses it during the build to discover its imports and exports. It also tries to resolve imports automatically and emits bindings tailored to your bundler.

The shape of those bindings depends on your target environment:

  • Static bindings — if the environment supports top-level await and the module needs no imports object (or unwasm can resolve one for you), the .wasm file behaves like a regular ESM import.
  • Lazy bindings — if top-level await is unavailable, the module needs an imports object, or you set the lazy plugin option, unwasm exports a Proxy that you call as a function to instantiate the module with your own imports. The syntax stays close to ESM, and initialization happens only when you need it.

Example: Using static import

import { sum } from "sum.wasm";

Example: Using dynamic import

const { sum } = await import("sum.wasm");

If your module requires an imports object (which unwasm can often infer for you), the syntax changes slightly: you initialize the module with that object first.

Example: Using dynamic import with imports object

const { rand } = await import("rand.wasm").then((r) =>
  r.default({
    env: {
      seed: () => () => Math.random() * Date.now(),
    },
  }),
);

Example: Using static import with imports object

import initRand, { rand } from "rand.wasm";

await initRand({
  env: {
    seed: () => () => Math.random() * Date.now(),
  },
});

Note

With static import syntax, named exports are proxied until the module is initialized. If you call one of them before init, the proxy runs init without imports and returns a Promise that resolves with the call's result.

Module compatibility

Some libraries want a WebAssembly.Module so they can create the WebAssembly.Instance themselves. For those cases, add the ?module suffix to import a .wasm file as a Module directly.

import _sumMod from "sum.wasm?module";
const { sum } = await WebAssembly.instantiate(_sumMod).then((i) => i.exports);

Note

Run into a library that needs this? Open an issue — we would love to help it migrate!

Integration

unwasm transforms .wasm imports into compatible bindings at build time. Today that happens through a Rollup plugin or a dedicated Rspack plugin; more integrations are planned.

Install

Install the unwasm npm package:

# ✨ Auto-detect package manager
npx nypm install unwasm

Builder Plugins

Rollup
// rollup.config.js
import { unwasm } from "unwasm/plugin";

export default {
  plugins: [unwasm({/* options */})],
};

The same plugin works with Rolldown and Vite.

Rspack

Requires Rspack 2 or later.

// rspack.config.mjs
import { unwasmRspack } from "unwasm/plugin/rspack";

export default {
  plugins: [unwasmRspack({/* options */})],
};

Note

With esmImport: true, Rspack must emit ESM output (for example output.library.type: "modern-module") so that the generated import() of the .wasm asset is preserved.

Plugin Options

  • esmImport (default: false): Import the .wasm file directly instead of bundling it. Required on Cloudflare Workers, and works in any environment with native .wasm module imports.
  • lazy (default: false): Import .wasm files through a lazily evaluated proxy, for runtimes without top-level await.

Tools

unwasm ships build-time helpers for working with .wasm modules directly.

parseWasm

Parses the wasm binary format to extract a module's imports and exports. It is a small, dependency-free reader that decodes only the sections describing the module interface and skips the rest.

import { readFile } from "node:fs/promises";
import { parseWasm } from "unwasm/tools";

const source = await readFile(new URL("examples/sum.wasm", import.meta.url));
const parsed = parseWasm(source);
console.log(JSON.stringify(parsed, undefined, 2));

Example parsed result:

{
  "modules": [
    {
      "exports": [
        {
          "id": 5,
          "name": "rand",
          "type": "Func"
        },
        {
          "id": 0,
          "name": "memory",
          "type": "Memory"
        }
      ],
      "imports": [
        {
          "module": "env",
          "name": "seed",
          "params": [],
          "returnType": "f64"
        }
      ]
    }
  ]
}

Auto Imports

unwasm can infer the imports object for you and bundle it using import maps (read more: MDN, Node.js, and WICG).

To tell the bundler how to resolve the imports a .wasm file needs, declare them in a parent package.json:

{
  "exports": {
    "./rand.wasm": "./rand.wasm"
  },
  "imports": {
    "env": "./env.mjs"
  }
}

Tip

You can prefix import names with # (for example #env) to follow Node.js conventions.

Wasm ESM Imports

Wasm modules can also import from ES modules (read more: ESM Integration Spec).

Example:

(module
  (import "./add-esmi-deps.mjs" "getValue" (func $getValue (result i32)))

  (func (export "addImported") (param $a i32) (result i32)
    local.get $a
    call $getValue
    i32.add
  )
)

Contribution

Local development
  • Clone this repository
  • Install the latest LTS version of Node.js
  • Enable Corepack using corepack enable
  • Install dependencies using pnpm install
  • Run tests using pnpm dev or pnpm test

License

Published under the MIT license. Made by @pi0 and community 💛


🤖 auto updated with automd

About

🇼 WebAssembly tools for JavaScript

Resources

Readme
MIT license
Activity
Custom properties

Stars

311 stars

Watchers

1 watching

Forks

14 forks
Report repository

Releases

Used by

Contributors

Languages

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.