Error when loading rhino3dm.js on a NextJs/React project

Hi,

I am trying to use rhino3dm.js on a NextJs/React project.

export default function Home() {
  const onClick = useCallback(() => {
    rhino3dm().then((Module) => {
      const sphere = new Module.Sphere([0, 0, 0], 16);
      console.log(`rhino3dm sphere:${sphere.radius}`);
    });
  }, []);

  return (
    <div className={styles.container}>
      <main>
        <h1>Rhino Compute Test</h1>
        <button onClick={onClick}> Load rhino3dm</button>
      </main>
    </div>
  );
}

When executing the promise rhino3dm().then() some problems come along trying to load the wasm file and the next error appear:

rhino3dm.js?6024:9 Uncaught (in promise) RuntimeError: abort(both async and sync fetching of the wasm failed). Build with -s ASSERTIONS=1 for more info.
    at abort (rhino3dm.js?6024:9:13992)
    at getBinary (rhino3dm.js?6024:9:14705)
    at eval (rhino3dm.js?6024:9:15077)

I have tried some settings on webpack but non of them had worked so far. Currently this is my current settings on next.config.js:

const nextConfig = {
  reactStrictMode: true,
  future: {
    webpack5: true,
  },
  webpack: (config, { dev }) => {
    config.resolve.fallback = {
      ...config.resolve.fallback,
      fs: false,
    };
    config.experiments = {
      asyncWebAssembly: true,
      syncWebAssembly: true,
    };
    return config;
  },
};

module.exports = nextConfig;

I also tried to put the wasm file on my public directory but that did not work either.

To replicate the error, I just created a nextjs project with rhino3dm and the above code in here.

I am unsure what could help me to solve my current error so any help would be very much appreciated.

I am having the same issue, and what I did is not what I would call a solution, but it does make things work in dev.

So I went to the debugger in my browser and found that the rhino3dm.js script is looking for rhino3dm.wasm in E:\GitLab\BIM-tests\.next\static\chunks\pages which is where next puts compiled files.

So I put the .wasm file from the node_module there

This makes my program run, however I don’t know the correct way to make next (or rhino3dm) look for or ship the script in a place that makes sense.

Also side note, very funny that you and I both run into this issue at the same time as I started trying this yesterday and was looking here for an answer to this questions as well :stuck_out_tongue_winking_eye:

I was able to (with the help of copy-webpack-plugin) automate this. All I needed to do was add that node module then update my next.config.js

/** @type {import('next').NextConfig} */

const CopyPlugin = require("copy-webpack-plugin");

const nextConfig = {
  reactStrictMode: true,
  webpack5: true,
  webpack: (config) => {
    
    config.resolve.fallback = { fs: false };

    config.plugins.push(
      new CopyPlugin({
        patterns: [
          { from: "node_modules/rhino3dm/rhino3dm.wasm", to: "static/chunks/pages/"}
        ]
      })
    )

    return config;
  },
}

module.exports = nextConfig

I would also prefer that this not be required but for now this is what we’ve got to work with I suppose.

I hope this helps!

Thanks @brandon.m.davis , very much appreciated!, apologies for the late response, got side tracked as I noticed as well that someone solved this issue in Vue.

And while jumping in this wagon, I agree also with Chuck_Driesler:

This appears to be a hacky way to force any emscripten generated wasm to hop over whatever webpack is trying to do with it.

You can also reference it in your index.html

just to add my two cents to this, I’m using Vite + React and also ran into this issue. One way to resolve it is to find the .wasm file in the node modules and manually copy it into the /public directory. that removed my errors

Is there a more standard way to do this? I cannot discern if this is an issue with rhino3dm, webpack, or the framework (vue, vite, etc)?

For now I have the lib referenced in index.html in some adjacent folder. Here is a vite example I did last week: rhino-developer-samples/rhino3dm/js/SampleVite at 8 Ā· mcneel/rhino-developer-samples Ā· GitHub

edit: ok, I see this is a general issue with webpack and handling all webassembly cases

After some digging, I updated the vite example to enable the what I believe people are asking for. To do this (for vite, which uses rollup), I had to do the following:

  1. Import rhino3dm: npm i rhino3dm
  2. Change the ā€˜main’ entry file to rhino3dm to use the module. This change is in node_modules/rhino3dm/package.json: ā€œmainā€: ā€œrhino3dm.module.jsā€
  3. Create a vite.config.js file in the root of the project with the following contents:
import {defineConfig} from 'vite'
export default defineConfig({
  optimizeDeps: {
    exclude: ['rhino3dm'],
  },
});

Hey Luis, thanks for figuring it out.

The idomatic way to do this is in vite would be.

Steps this way are:

  1. Import rhino3dm: npm i rhino3dm
  2. Create a vite.config.js file in the root of the project with the following contents:
export default defineConfig({
  plugins: [vue()],
  // exclude rhino3dm from optimization
  optimizeDeps: {
    exclude: ['rhino3dm']
  },
  // use the rhino3dm.module.js entrypoint
  resolve: {
    alias: {
      'rhino3dm': path.resolve(__dirname, 'node_modules/rhino3dm/rhino3dm.module.js')
    }
  }
})