Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use WebAssembly (wasm) with create-react-app

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 command my build is failed:

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
like image 969
Pavel Avatar asked Dec 13 '19 09:12

Pavel


People also ask

Can you use WebAssembly With React?

Use-as-bind is a React hook that allows developers to load and instantiate WebAssembly created with AssemblyScript and the AsBind loader.

Can you use WebAssembly in react native?

A polyfill to use WebAssembly in React Native. This package instantiates WebAssembly in a native WebView environment and makes the communication with React Native to simulate original behavior.

Why is WebAssembly faster than JavaScript?

Unlike Javascript, WASM is statically typed, which means code optimization occurs far earlier in the compilation process before the code reaches the browser. Its binary files are considerably smaller than JavaScript's, resulting in significantly faster loading times.

Will WebAssembly replace React?

But don't worry — WebAssembly will certainly not replace our beloved frameworks like React (yeah, it's a library, but you get the point), Vue, and Angular. The thing is, they could benefit greatly from WebAssembly. Let's take a look at this using React.


1 Answers

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"
  }
}
like image 161
Michael Avatar answered Sep 23 '22 21:09

Michael