Import WASM into webworker synchronously using Webpack

Viewed 314

I've been following the wasm_bindgen guides to create wasm from rust. Those work fine and I have some code that can be loaded in my main app.

That loading works sometimes, but frequently not, with my main program's initialization hanging. A race condition?

We are loading the wasm directly into a webworker. So, whereas as normally wasm has to be loaded asynchronously, that requirement does not hold within web-workers. Forcing synchronous loading is what I would like to do to see whether this creates more consistent behavior, whatever the performance consequences

Here's my setup

  • compile rust with wasm-pack build (or with wasm-pack build --target web)
  • copy the ./pkg/* output into my main codebase
  • in the main code
// pkg contains the assets from the wasm_bindgen example
import {greet} from "./pkg";
console.log("****after import")
function ffi_greet(connector, args) {
    console.log("*****GREET*********", args)
    return greet(args[0])
}

In my webpack.config.js I have:

        experiments: {
            asyncWebAssembly: true,
        }

The code does look synchronous, but I presume that webpack is loading wasm asynchronously. My question is how can I force synchronous wasm loading (in a webworker)

2 Answers

While wasm-pack tries to make it easy to automate the loading of the WASM code into your application, it still allows applications to fairly freely change how it does it.

For example, in one of the applications we wrote at work, we decided to embed the WASM binary into the HTML page itself (we had reasons).

The WASM loader looks like this:

webpack.wasm-loader.js

module.exports = function (buffer) {
    const wasm = buffer.toString('base64');
    return `module.exports = Uint8Array.from(atob('${wasm}'), c => c.charCodeAt(0));`;
};

Then, in webpack.config.js:

    module: {
        rules: [{
            test: /\.wasm$/,
            use: [{
                loader: path.resolve('webpack.wasm-loader.js'),
            }]
        }],
    },

The initializer script does something like this:

import init from '../pkg/my_lib';
import wasm from '../pkg/my_lib_bg.wasm';

init(wasm);

I do not think that you need webpack configuration to load wasm packages into javascript.

  • Since you have pkg directory in your codebase, from pkg/package.json file get the name (let's say name:my_wasm_project) and add it to your javascript project's package.json

    "dependencies": {
      "webpack": "^5.67.0",
      "webpack-cli": "^4.9.1",
       // adding the path pkg
      "my_wasm_project": "file:../pkg"
    }, 
    
  • in your javascript project, run npm install. this will add your wasm built into the node_modules.

  • Now inside any javascript file you can import it:

    import init, { greet } from "my_wasm_project";
    
Related