2

I am trying to build a Next JS project with an imported WebAssembly module compiled using Emscripten. The problem seems to be related to the WebPack loader being unable to import the .wasm module via the generated .js. I would greatly appreciate some help.

My C++ file hello.cpp:

#include <math.h>

extern "C" {

int int_sqrt(int x) {
  return sqrt(x);
}

}

I compile using:

em++ hello.cpp -o "../v2/lib/wasm/test.js" -s MODULARIZE -s WASM=1 -s EXPORT_NAME="SZU" -s ENVIRONMENT="web" -s EXPORTED_FUNCTIONS=_int_sqrt -s EXPORTED_RUNTIME_METHODS=ccall,cwrap

I try to use the module in one of the components like so:

import SZU from "../../../../../../wasm/test";
var int_sqrt = SZU().cwrap("int_sqrt", 'number', ['number'])

When I run npx next build the build fails with:

Error: not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)

I expect to be able to build the project using npx next build then start the server with npx next start and be able to interact with functions exported in the .wasm/.js module files generated by Emscripten.

2 Answers 2

2

With the help of @lab I realized my approach was wrong. This is the way I made my WASM module work:

  1. This is my hello.cpp file. Important notice the extern "C" {} block:
#include <math.h>

extern "C" {

int int_sqrt(int x) {
  return sqrt(x);
}

}
  1. I compile using em++ the destination is the public folder in next. We need to serve the .wasm and .js statically like @lab pointed out:
em++ hello.cpp -o "../v2/public/wasm/test.js" -s MODULARIZE -s WASM=1 -s EXPORT_NAME="SZU" -s ENVIRONMENT="web" -s EXPORTED_FUNCTIONS=_int_sqrt -s EXPORTED_RUNTIME_METHODS=ccall,cwrap
  1. I load the Emscripten generated js file using the next/script tag like so:
<Script src="/wasm/test.js" strategy='beforeInteractive'/>
  1. In the Component I want to use my WASM module I load it inside the next/useEffect hook, wrap it with Emscripten cwrap and store the function in a reference object using next/useRef like so:
useEffect(() => {
    if(typeof (window as any).SZU === 'function' && WASM.current === null){
        console.log("loading WASM!");
        (window as any).SZU()
            .then((wasm: WASM) => {
                console.log("got WASM!");
                WASM.current = wasm;
                int_sqrt.current = WASM.current.cwrap("int_sqrt", "number", ["number"]);
            });
    }
}, []);
  1. I can call the function later like so:
console.log(`Square root of 16 is ${int_sqrt.current(16)}`);

I hope this helps someone who had the same problem.

Sign up to request clarification or add additional context in comments.

Comments

1

The case for wasm is that it will compile into 2 files: a js file and a wasm file. The wasm file cannot be bundled into your app. You must serve it as a static asset (since it's basically binary code), and configure your path to align with your desired import.

Also you might want to ensure it work first. Try writing a nodejs script that import it and give it a test run. OR you can try import it into a nextjs API route, and invoke it via fetch from client-side and see if your compiled wasm work.

3 Comments

When I put test.js and test.wasm in the public/wasm folder I can load the module like so: <Script src="/wasm/test.js" strategy='beforeInteractive'/> and call the WASM functions like so in the DevTools console: window.SZU().then(module => {console.log(module._int_sqrt(8))}); That works!
So the wasm module is compiled successfully and I can call my functions at runtime in the browser. Now I'm trying to figure out how to load it in my React Components and use it in the useEffect hook.
You can likely just use the exact same code above with a window check + useRef to referencing the module

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.