如何在本地加载 wasm 模块?

Posted

技术标签:

【中文标题】如何在本地加载 wasm 模块?【英文标题】:How to load a wasm module locally? 【发布时间】:2020-07-18 00:44:56 【问题描述】:

我正在尝试使用 javascript 和 WebAssembly 制作一个简单、自包含(只有一个 .html 文件和一个 .wasm 文件)的离线数据可视化。但是,我无法从本地文件加载 WASM 模块。

第一个麻烦是CORS。尝试使用相对 URL 或 file:// URL 加载任何 JS 模块都会出现安全错误。在 Firefox 上,我设法禁用了本地 CORS,但这很恶心而且过于宽容。在 Chrome 上,我需要使用标志启动浏览器。从用户的角度来看,这些都不是初学者。有没有办法从本地文件加载 JS 或 WASM 模块而不会遇到 CORS 问题?

绕过CORS,第二个麻烦是,虽然Firefox能够加载JS模块,但WASM模块失败:(我的实际错误消息是日文的,但我认为这是英文的)'Loading failed for带有源的“.wasm”。没有显示更多信息。在 Chrome 上,错误消息是“加载模块脚本失败:服务器以非 JavaScript MIME 类型“”响应。根据 HTML 规范对模块脚本强制执行严格的 MIME 类型检查。',这表明两种浏览器都可能无法猜测 MIME 类型。

这两个问题都可以通过设置一个 HTTP 服务器来解决,但这完全违背了拥有一个只需要浏览器即可运行的简单、自包含文件的目的。

有没有办法仅使用本地文件加载和调用 WASM?

【问题讨论】:

【参考方案1】:

您可以将 wasm 编码为 base64,然后像这样加载它(据我所知没有大小限制 - 绝对适用于 5Mb+)

Module.wasmBinaryFile="data:application/wasm;base64,AGFzbQEAAAABww...

【讨论】:

【参考方案2】:

您可以将 Wasm 二进制文件内联为 Uint8Array,并以这种方式实例化它。不过,它只有在足够小的情况下才有效。如果 Wasm 超过 4KB,我相信您会收到错误消息。

// your Wasm file as a Uint8Array
const wasmSourceCode = new Uint8Array([0, 97, 115, 109 ...]);
const wasmModule = new WebAssembly.Module(wasmSourceCode );
const wasmInstance = new WebAssembly.Instance(wasmModule);

【讨论】:

以上是关于如何在本地加载 wasm 模块?的主要内容,如果未能解决你的问题,请参考以下文章

如何加载存储在子目录中的 .wasm 文件?

使用 wasm 将模块导入并编译到 webpack 中

WASM 中的环境检测:Web、Node.js 还是独立运行时?

如何满足对 wasm 的严格 mime 类型检查?

如何在 NEAR 协议中构建和部署多个合约

FLARE脚本系列:使用idawasm IDA Pro插件逆向WebAssembly(Wasm)模块