Elias
Elias

Reputation: 4112

Rust wasm in next js

I am trying to use a rust-generated wasm module inside of my NextJs project.

I am importing the wasm in the following way:

import init, { tokenize } from "@/wasm/lazyjson";

const Test = dynamic({
    loader: async () => {
        await init();

        console.log(tokenize("[]"));

        return function Yay() {
            return <p>hi</p>;
        };
    },
});

I've also tried to import it with:

const { default: init, tokenize } = await import("@/wasm/lazyjson");

This results in

TypeError: Only absolute URLs are supported

As of webpack 5 (which NextJs uses) WebAssembly is supported by default (I think). So this is my next.config.js / webpack config:

module.exports = {
    webpack: (config) => {
        config.resolve.alias["@/"] = __dirname;

        return config;
    },
};

I've tried adding the syncWebAssembly flag

config.experiments = { syncWebAssembly: true };

which results in a different error:

Module not found: Can't resolve 'wbg' in '[project-path]\wasm\lazyjson'

If you're confused about the question or need more context please check out the issue I opened here. It also contains steps to reproduce.

Upvotes: 3

Views: 3672

Answers (2)

Yuri Gor
Yuri Gor

Reputation: 1463

If it's fine for you to expose wasm file in static or public folder, so anyone could potentially grab it, then you can do as Yilmaz suggested and fetch wasm module yourself. After that you can still use your package generated by wasm-pack. That init function accepts optional module argument, so if you do

const buffer = await res.arrayBuffer();

then you can pass that buffer ti init function and it will not try fetch it himself.

Also experiment with --target parameter of wasm-pack command, "web" target would possibly work better rather then "nodejs" (not sure how did you build your package)

If it's not fine to expose wasm file to the public and you want to run it exceptionally on server side (like in API only) then it will be much bigger problem.

Upvotes: 0

Yilmaz
Yilmaz

Reputation: 49190

instead of relying on third part library, place your wasm folder into the public folder and simply fetch it in the client side.

async function getWasm() {
  try {
    const res = await fetch("test.wasm");
    // bytes from memory
    const buffer = await res.arrayBuffer();
    // this will create an object
    // WebAssembly is part of window api. so make sure you are on client side. 
    const wasm = await WebAssembly.instantiate(buffer);
    console.log(wasm);
    // this is the method defined in wasm code
    // you need to know what methods are defined in your source code
    const addNumbers = wasm.instance.exports.addTwo;
    // console.log(addNumbers);
    const result = addNumbers(100, 50);
    console.log(result);
  } catch (e) {
    console.log(e);
  }
}

Upvotes: 2

Related Questions