如何将 WebAssembly (wasm) 与 create-react-app 一起使用



我使用create-react-app和库,wasm它被称为萨克斯-wasm。 稍微修改了网络的示例代码,我得到了这个:

import { SaxEventType, SAXParser } from 'sax-wasm';
async function loadAndPrepareWasm() {
const saxWasmResponse = await import('sax-wasm/lib/sax-wasm.wasm');
const saxWasmbuffer = await saxWasmResponse.arrayBuffer();
const parser = new SAXParser(SaxEventType.Attribute | SaxEventType.OpenTag, {
highWaterMark: 64 * 1024,
});
const ready = await parser.prepareWasm(new Uint8Array(saxWasmbuffer));
if (ready) {
return parser;
}
}
loadAndPrepareWasm().then(console.log);

当我运行yarn start命令时,我的构建失败:

Failed to compile.
./node_modules/sax-wasm/lib/sax-wasm.wasm
Module parse failed: magic header not detected
File was processed with these loaders:
* ./node_modules/file-loader/dist/cjs.js
You may need an additional loader to handle the result of these loaders.
Error: magic header not detected

以下解决方案适用于 CRA 3.x。对于CRA 4.x,您应该使用craco。

CRA不支持WASM。但是您可以解决它。您需要覆盖 webpack 配置。有多个软件包可以做到这一点。我使用了react-app-rewired。你需要 wasm 加载器包

比添加覆盖配置覆盖.js

const path = require('path');
module.exports = function override(config, env) {
/**
* Add WASM support
*/
// Make file-loader ignore WASM files
const wasmExtensionRegExp = /.wasm$/;
config.resolve.extensions.push('.wasm');
config.module.rules.forEach(rule => {
(rule.oneOf || []).forEach(oneOf => {
if (oneOf.loader && oneOf.loader.indexOf('file-loader') >= 0) {
oneOf.exclude.push(wasmExtensionRegExp);
}
});
});
// Add a dedicated loader for WASM
config.module.rules.push({
test: wasmExtensionRegExp,
include: path.resolve(__dirname, 'src'),
use: [{ loader: require.resolve('wasm-loader'), options: {} }]
});
return config;
};

package.json中,我是这样做的:

{
...
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject",
"predeploy": "npm run build",
"deploy": "gh-pages -d build"
},
...
"devDependencies": {
"react-app-rewired": "2.1.3",
"wasm-loader": "1.3.0"
}
}

你最终想在浏览器中使用 wasm。这意味着您必须在浏览器中访问它。

我安装了esbuild-wasm。有两种方法可以设置它:

1-在节点模块中找到模块"node_modules/esbuild-wasm",您将看到一个文件"esbuild-wasm"并将其放在公共文件夹中。这已经编译好的代码可以直接在浏览器中工作。内部组件:

import * as esbuild from "esbuild-wasm"
import {useRef, useState} from "react"
// you can use ref to keep a reference to any Js value inside of a component. 
const ref=useRef()
const startEsbuildService=async()=>{
// this object is responsible for transpiling
ref.current=await esbuild.startService({
worker:true,
// we are pointing to the public directory
wasmURL:'/esbuild.wasm'})
}

第二种方式:

const startEsbuildService = async () => {
ref.current = await esbuild.startService({
worker: true,
// unpkg.com provides all npm modules without CORS error
wasmURL: "https://unpkg.com/esbuild-wasm@0.8.42/esbuild.wasm",
});
};

这就是你使用它的方式

// you store the code
const [codeInput,setCodeInput]=useState("")
const [transpiledCode,setTranspiledCode]=useState("")
const onClick= async ()=>{
if(!ref.current) return;
const transformedCode=await ref.current.transform(codeInput,{
// es-build can handle different types of code
loader:'jsx',
target: 'es2015'})
// this will rerender our component
setTranspiledCode(transformedCode)
}

相关内容

  • 没有找到相关文章

最新更新