Rust wasm in next js
Asked Answered
T

2

3

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.

Twelve answered 4/7, 2021 at 13:46 Comment(5)
Hard to comment without the webpack config, I've had similar problems when the js loader tries to load the wasm file, try adding /\.wasm$/it to the exclusions pattern so it gets bundled as a normal file (and keep using the await import syntax)Jot
@MathieuRene I've added my WebPack config :). People developing this stuff really make it difficult to use it, especially for beginner that don't know the ins and outs of every tool ever.Twelve
Did you try enabling webassembly support as in github.com/vercel/next.js/blob/canary/examples/with-webassembly/… ?Jot
@MathieuRene No, I haven't tried that. Did add that now (btw you need to be on webpack 5). But now as soon as I tried to import the wasm file I get Module not found: Can't resolve 'wbg' in <project directory>. Problems after problems :(Twelve
I've updated the question accordinglyTwelve
L
2

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);
  }
}
Ludmilla answered 23/1, 2022 at 12:46 Comment(5)
Best answer I stumble upon today.Joanejoanie
but it doesn't work, in the instantiate function we need to provide the imports which I have no idea how to provide. the wasm-bindgen provided js file has thoseJoanejoanie
@JustinZhang send me your codeLudmilla
thanks, here is my code github.com/voidcenter/import-wasm-into-nextjs. Here (github.com/voidcenter/import-wasm-into-nextjs/blob/main/…) is the recommended way to import wasm-bindgen code into js but I can't get it to work. Here (github.com/voidcenter/import-wasm-into-nextjs/blob/main/…) is the method in this answer, which complains about missing imports. Thanks!Joanejoanie
@JustinZhang can you follow my answer here: #65000709 this will helpLudmilla
C
0

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.

Cuba answered 26/7, 2022 at 14:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.