admin管理员组

文章数量:1287536

I use create-react-app and library with wasm its called sax-wasm. Slightly modifying the sample code for the web I got this:

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);

When I running yarn start mand my build is failed:

Failed to pile.

./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

I use create-react-app and library with wasm its called sax-wasm. Slightly modifying the sample code for the web I got this:

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);

When I running yarn start mand my build is failed:

Failed to pile.

./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
Share Improve this question edited Jan 1, 2024 at 20:16 Arnold Schrijver 3,7633 gold badges40 silver badges67 bronze badges asked Dec 13, 2019 at 9:39 Pavel PerevezencevPavel Perevezencev 2,9784 gold badges31 silver badges53 bronze badges 1
  • I assume this is the appropriate upstream issue to track / upvote. – bluenote10 Commented Jun 14, 2021 at 6:50
Add a ment  | 

2 Answers 2

Reset to default 5

The following solution is for CRA 3.x. For CRA 4.x you should use craco.

CRA does not support WASM. But you can workaround it. You need to override webpack config. There are multiple packages that can do it. I used react-app-rewired. And you need the wasm-loader package

Than add your override config-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;
};

In package.json I did it like this:

{
...
  "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"
  }
}

You eventually want to use the wasm inside the browser. That means you have to access it inside the browser.

I installed esbuild-wasm. There are two ways to set up this:

1- in node modules find the the module "node_modules/esbuild-wasm" you will see a file "esbuild-wasm" and place it inside public folder. This has the piled code can directly work inside the browser. Inside ponent:

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 ponent. 
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'})
}

2nd way:

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

This is how you use it

 // 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 ponent
   setTranspiledCode(transformedCode)
}

本文标签: javascriptHow to use WebAssembly (wasm) with createreactappStack Overflow