背景
- webAssembly文件(xxx.wasm)只能通过ajax请求的形式进行引入。参见: https://developer.mozilla.org/zh-CN/docs/WebAssembly/JavaScript_interface
- package中直接通过本地形式加载wasm文件会导致在项目中使用的路径问题,如下所示
const wasm = window.fetch('../static/dd.wasm')
解决方式
方案一
package封装后,将wasm文件提供在包内,由业务使用方自行引入。如:
// 以vue3 使用形式做说明
import PACK from 'pack';
onMounted(()=>{
new PACK({
wasmPath: new URL('../node_modules/pack/static/dd.wasm', import.meta.url).href
})
})
方案二
package内部通过远程形式加载,如:
const wasm = window.fetch('https://test.tt.com/static/dd.wasm');
方案三
在package打包时,将wasm文件通过fs模块进行内容读取,然后将wasm文件内容转换成unit8Array,写到wasm.js文件中。然后package主文件引入wasm.js进行引入即可。
- wasm读取存储,如:
// build.js
// const fs = require('fs');
import * as fs from 'fs'
// 读取 .wasm 文件并将其转换为 ArrayBuffer
const arrayBuffer = fs.readFileSync('./static/dd.wasm').buffer;
// 将 ArrayBuffer 中的二进制数据存储到数组中
const binaryData = [];
const view = new Uint8Array(arrayBuffer);
for (let i = 0; i < view.length; ++i) {
binaryData.push(view[i]);
}
// 将二进制数据保存到 js 文件中
const tsCode = `export const wasmBinary = new Uint8Array([${binaryData.join(',')}]);`;
fs.writeFileSync('./src/utils/dd.js', tsCode);
- 执行命令
node ./build.js
- package主逻辑引入,如:
import {wasmBinary} from './utils/dd.js';
...
const wasmBlob = new Blob([wasmBinary], { type: "application/wasm" });
const wasmUrl = URL.createObjectURL(wasmBlob);
const res = window.fetch(wasmUrl);
const { instance } = await WebAssembly.instantiateStreaming(res, {});
...
如果是通用类型的package建议使用方案三,否则还需要在nginx层配置对应的MIME TYPE对application/wasm这种类型进行支持。