Skip to content
This repository has been archived by the owner on Oct 17, 2021. It is now read-only.

Integrating with create-react-app #3

Closed
cimi opened this issue Jul 24, 2017 · 8 comments
Closed

Integrating with create-react-app #3

cimi opened this issue Jul 24, 2017 · 8 comments

Comments

@cimi
Copy link

cimi commented Jul 24, 2017

I'm trying to use wasm-loader with create-react-app and I'm having some trouble getting it to work.

I'm using react-app-rewired to override the configuration:

module.exports = function override(config, env) {
  config.module.rules.push({
    test: /\.wasm$/,
    include: '/code/wasm-test/src',
    use: [require.resolve('wasm-loader')]
  });
  config.module.rules.forEach(rule => console.dir(rule));
  return config;
}

I've tried several different variants of this, got the same result for all of them (instead of use, reference loader directly, have an object with loader and options inside use, omit include).

The registration seems to work fine, and checking the output from the rules it seems that the rule for wasm-loader is added correctly:

{ test: /\.(js|jsx)$/,
  enforce: 'pre',
  use:
   [ { options: [Object],
       loader: '/code/wasm-test/node_modules/eslint-loader/index.js' } ],
  include: '/code/wasm-test/src' }
{ exclude:
   [ /\.html$/,
     /\.(js|jsx)$/,
     /\.css$/,
     /\.json$/,
     /\.bmp$/,
     /\.gif$/,
     /\.jpe?g$/,
     /\.png$/ ],
  loader: '/code/wasm-test/node_modules/file-loader/index.js',
  options: { name: 'static/media/[name].[hash:8].[ext]' } }
{ test: [ /\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/ ],
  loader: '/code/wasm-test/node_modules/url-loader/index.js',
  options: { limit: 10000, name: 'static/media/[name].[hash:8].[ext]' } }
{ test: /\.(js|jsx)$/,
  include: '/code/wasm-test/src',
  loader: '/code/wasm-test/node_modules/babel-loader/lib/index.js',
  options:
   { babelrc: false,
     presets: [ '/code/wasm-test/node_modules/babel-preset-react-app/index.js' ],
     cacheDirectory: true } }
{ test: /\.css$/,
  use:
   [ '/code/wasm-test/node_modules/style-loader/index.js',
     { loader: '/code/wasm-test/node_modules/css-loader/index.js',
       options: [Object] },
     { loader: '/code/wasm-test/node_modules/postcss-loader/lib/index.js',
       options: [Object] } ] }
{ test: /\.wasm$/,
  use: [ '/code/wasm-test/node_modules/wasm-loader/index.js' ] }

However, when trying to load wasm files I get not found failures:

import Counter from './wasm/counter';
// import fails on module not found
// if I replace with './wasm/counter.wasm' I get the file name as the value of the import
// non-existent file names (e.g. './wasm/counter2.wasm') also trigger not found, as expected
const wasmHelloWorld = () => {
  console.dir(Counter);    
}
window.onload = wasmHelloWorld;

Any idea what might be the issue?

Thanks for building this by the way, I can see it being really useful!

@cimi
Copy link
Author

cimi commented Jul 24, 2017

I managed to get it working by adding the .wasm extension to config.resolve.extensions and adding the wasm rule to the fileLoader exclusions. I ended up with this in config-overrides.js:

// through this file we can override the default cra configuration
// see: https://github.com/timarney/react-app-rewired
const path = require('path')

module.exports = function override(config, env) {
  const wasmExtensionRegExp = /\.wasm$/;

  config.resolve.extensions.push('.wasm');
  // make the file loader ignore wasm files
  const fileLoader = config.module.rules
    .find(rule => rule.loader && rule.loader.endsWith(`${path.sep}file-loader${path.sep}index.js`));
  fileLoader.exclude.push(wasmExtensionRegExp);

  // and add a dedicated loader for them
  config.module.rules.push({
    test: wasmExtensionRegExp,
    include: path.resolve(__dirname, "src"),
    use: [{loader: require.resolve('wasm-loader'), options: {}}]
  });
  return config;
}

Now I'm hitting another issue (Chrome 59):

WebAssembly.Compile is disallowed on the main thread, if the buffer size is larger than 4KB. Use WebAssembly.compile, or compile on a worker thread.

This seems to be unrelated to the loader, so resolving this issue.

@cimi cimi closed this as completed Jul 24, 2017
@DanielRamosAcosta
Copy link

DanielRamosAcosta commented Nov 26, 2018

@cimi I'm having this error:

./src/wasm/testingwasm.wasm
Module parse failed: magic header not detected
You may need an appropriate loader to handle this file type.
Error: magic header not detected

Any ideas?

@ballercat
Copy link
Owner

Sounds like a corrupted module. It could happen because of a number of different reasons.

wabt the WebAssembly binary toolkit has a few very useful tools available online, one of which allows you to upload a wasm module, validate it and convert to the text format: wasm2wat.

Upload your file there to test whether or not the file is actually valid to begin with.

@AThilenius
Copy link

AThilenius commented Feb 2, 2019

I spent forever looking or a solution to this, so hoping this saves someone some time. New version of CRA seems to have rearranged the file-loader rule. My hack is:

// through this file we can override the default cra configuration
// see: https://github.com/timarney/react-app-rewired
const path = require('path');

module.exports = function override(config, env) {
  const wasmExtensionRegExp = /\.wasm$/;

  config.resolve.extensions.push('.wasm');
  // make the file loader ignore wasm files
  let fileLoader = null;
  config.module.rules.forEach(rule => {
    (rule.oneOf || []).map(oneOf => {
      if (oneOf.loader && oneOf.loader.indexOf('file-loader') >= 0) {
        fileLoader = oneOf;
      }
    });
  });
  fileLoader.exclude.push(wasmExtensionRegExp);

  // Add a dedicated loader for them
  config.module.rules.push({
    test: wasmExtensionRegExp,
    include: path.resolve(__dirname, 'src'),
    use: [{ loader: require.resolve('wasm-loader'), options: {} }],
  });
  return config;
};

Note: that needs to go into config-overrides.js, same dir as package.json. You also need to npm install --save-dev react-app-rewired and replace the scripts in package.json:

    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test --env=jsdom",

I read a bit that CRA 2+ can do this, so unsure if react-app-rewired is strictly necessary?


For building WASM that can be consumed, easiest way is to use wasm-pack, which will create a pkg directory. I put all the Rust stuff off the root dir into native. Then in package.json you can import pkg (which is a npm module) via:

  "dependencies": {
    "native": "file:../native/pkg",
  }

Finally, this must be async loaded, so my index.tsx is:

// The wasm must load async. Just wait to load anything else until it's done.
async function loadNative() {
  await import('native');
  await import('./app');
}

loadNative();

@prichey
Copy link

prichey commented Mar 4, 2019

This blog post might be helpful for future visitors (using @AThilenius' answer above!): https://prestonrichey.com/blog/react-rust-wasm/

@yw662
Copy link

yw662 commented Mar 6, 2019

I encountered with

> react-app-rewired start
Starting the development server...

Failed to decode custom "name" section @50458; ignoring (integer representation too long).
Failed to compile.

./recognizer/pkg/recognizer_bg.wasm
Module parse failed: Unexpected section: 0x86
You may need an appropriate loader to handle this file type.
Error: Unexpected section: 0x86

I am following @prichey 's solution
The .wasm file is valid, can be disasm into .wast, and can be compiled directly in browser.
what should I do now ?

@yw662
Copy link

yw662 commented Mar 6, 2019

seems this is related to version issue of wasm-bindgen. change the line to =0.2.34 and it works.

@Noah-Huppert
Copy link

Note for future people @AThilenius :

As of 4/15/20 this solution still works. Here is a complete code example.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants