unwasm
适用于 JavaScript 的 WebAssembly 工具
适用于 JavaScript 的通用 WebAssembly 工具。
目标
本项目旨在为 WebAssembly 模块支持提供一个通用且面向未来的解决方案,适用于各种 JavaScript 运行时、框架和构建工具,尽可能遵循 WebAssembly 社区组的 WebAssembly/ES 模块集成 提案,同时努力保持与现有生态系统库的兼容性。
绑定 API
当导入 .wasm
模块时,unwasm 在构建过程中解析、读取并解析模块,以获取有关导入和导出的信息,甚至尝试自动解析导入并为打包工具生成适当的代码绑定。
如果目标环境支持顶层 await
且 wasm 模块不需要导入对象(或者它们可以自动解析),unwasm 会生成绑定,允许像导入任何其他 ESM 模块一样导入 wasm 模块。
如果目标环境不支持顶层 await
,或者 wasm 模块需要导入对象,或者 lazy
插件选项设置为 true
,unwasm 将导出一个包装的 Proxy 对象,该对象可以作为函数调用,以惰性地使用自定义导入对象评估模块。这样我们仍然可以拥有尽可能接近 ESM 模块的简单语法,并且可以惰性初始化模块。
示例:使用静态导入
import { sum } from "unwasm/examples/sum.wasm";
示例:使用动态导入
const { sum } = await import("unwasm/examples/sum.wasm");
如果您的 WebAssembly 模块需要导入对象(unwasm 可以自动推断它们),则用法语法会略有不同,因为我们首先需要使用导入对象初始化模块。
示例:使用带导入对象的动态导入
const { rand } = await import("unwasm/examples/rand.wasm").then((r) =>
r.default({
env: {
seed: () => () => Math.random() * Date.now(),
},
}),
);
示例:使用带导入对象的静态导入
import initRand, { rand } from "unwasm/examples/rand.wasm";
await initRand({
env: {
seed: () => () => Math.random() * Date.now(),
},
});
模块兼容性
有些情况下,库需要 WebAssembly.Module
实例来初始化其自身的 WebAssembly.Instance
。为了最大化兼容性,unwasm 允许使用特定的导入后缀 ?module
直接将 .wasm
文件作为模块导入。
import _sumMod from "unwasm/examples/sum.wasm?module";
const { sum } = await WebAssembly.instantiate(_sumMod).then((i) => i.exports);
集成
Unwasm 需要将 .wasm
导入转换为兼容的绑定。目前,唯一的方法是使用 Rollup 插件。未来将引入更多使用方法。
安装
首先,安装 unwasm
npm 包。
# ✨ Auto-detect
npx nypm install unwasm
# npm
npm install unwasm
# yarn
yarn add unwasm
# pnpm
pnpm install unwasm
# bun
bun install unwasm
构建器插件
Rollup
// rollup.config.js
import { rollup as unwasm } from "unwasm/plugin";
export default {
plugins: [
unwasm({
/* options */
}),
],
};
插件选项
esmImport
:直接导入 wasm 文件而不是打包,Cloudflare Workers 需要此项,并适用于允许原生导入.wasm
模块的环境(默认为false
)lazy
:使用惰性求值代理导入.wasm
文件,以兼容不支持顶层 await 的运行时(默认为false
)
工具
unwasm 提供有用的构建工具,可直接操作 .wasm
模块。
注意: unwasm/tools
子路径导出不适用于或优化用于生产运行时。仅在开发和构建时依赖它。
parseWasm
使用 webassemblyjs/wasm-parser 解析 wasm
二进制格式并获取有用的信息。
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));
解析结果示例
{
"modules": [
{
"exports": [
{
"id": 5,
"name": "rand",
"type": "Func"
},
{
"id": 0,
"name": "memory",
"type": "Memory"
}
],
"imports": [
{
"module": "env",
"name": "seed",
"params": [],
"returnType": "f64"
}
]
}
]
}
自动导入
unwasm 可以自动推断导入对象,并使用导入映射将其打包(了解更多:MDN、Node.js 和 WICG)。
为了提示打包工具如何解析 .wasm
文件所需的导入,您需要在父级 package.json
文件中定义它们。
示例
{
"exports": {
"./rand.wasm": "./rand.wasm"
},
"imports": {
"env": "./env.mjs"
}
}
注意:如果您希望遵循 Node.js 约定,导入也可以以 #
为前缀,例如 #env
。