javascript 如何使用WebAssembly(WASM)与Web-react-app

ddarikpa  于 5个月前  发布在  Java
关注(0)|答案(2)|浏览(62)

我使用create-react-app和库与wasm其所谓的sax-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

kyvafyod

kyvafyod1#

以下解决方案适用于CRA 3.x。对于CRA 4.x,您应该使用craco
CRA不支持WASM。但你可以解决它。你需要覆盖webpack config。有多个软件包可以做到这一点。我使用react-app-rewired。你需要wasm-loader软件包
然后添加您的override * js-overrides.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"
  }
}

vcirk6k6

vcirk6k62#

你最终想在浏览器中使用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/[email protected]/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)
}

相关问题