I try to load a C WebAssembly Module in a React Vite App inside a WebWorker. When loading the Module in the main thread everything works as expected and the wasm.js can locate the wasm.data file inside /public folder. But when loading the Module inside a Comlink Webworker the Module can not locate the .data file and throws following Error:
pFlowWeb.js:9 Uncaught Error: Not Found : http://localhost:5173/src/wasm/internal:comlink:../webWorker/pFlowWeb.data
at xhr.onload (pFlowWeb.js:9:2505)
For the worker i followed How to use Web Workers with React and Vite . The worker on its own works fine. Also the module loads fine inside the main thread.
The WebAssembly Module is compiled with following flags:
$EMSCRIPTEN_CC -O2 ... --preload-file 00Input/ \
-s ALLOW_MEMORY_GROWTH=1 -s --no-heap-copy -sFORCE_FILESYSTEM\
-s EXPORTED_FUNCTIONS="['_main']" \
-s EXPORT_ES6=1 -s ENVIRONMENT='web' -s MODULARIZE=1 -s USE_ES6_IMPORT_META=0 -o pFlowWeb.js ...
The Module is loaded like this
// wasmClient.ts
import pFLowWeb from "./pFlowWeb.js";
export class pFlowModule {
...
// initialize the module
setup = async () => {
this.module = await pFLowWeb();
};
...
}
in the same file the worker instance is declared
// wasmClient.ts
export const workerInstance = new ComlinkWorker<
typeof import("../webWorker/worker")
>(new URL("../webWorker/worker", import.meta.url));
Then finally the worker
// webWorker/worker.ts
/// <reference lib="webworker" />
declare const self: DedicatedWorkerGlobalScope;
import { pFlowModule } from "./../wasm/wasmClient";
export const setupModule = async () => {
const newModule = new pFlowModule();
await newModule.setup();
};
Which is then called in the main thread:
// Simulation.ts
import { workerInstance } from "../../wasm/wasmClient";
const handleInitClick = () => {
workerInstance.setupModule();
};
I had the module inside the web worker running in a Vue App by following the instructions from this post on How to Use WebAssembly Modules in a Web Worker . I tried to add webpack and the loaders to the react app but in my understanding vite should replace webpack and its loaders so i did not bring it to work.
Then i tried to include the wasm assets in the vite config
// https://vitejs.dev/config/
export default defineConfig({
plugins: [comlink(), react()],
worker: {
plugins: [comlink()],
},
assetsInclude: ["**/*.wasm", "**/*.data"],
});
which had no effect.
I have also taken a look at the Module.locateFile method of the web assembly Module. But i don't see how to call the method before initializing the module.
I worked it out! I used vite-static-copy plugin to create a copy of the files the wasm module needed and placed them at the destination it was looking for them.
Feels kinda hacky but works for me!
// vite.config.ts
import { viteStaticCopy } from "vite-plugin-static-copy";
export default defineConfig({
plugins: [
viteStaticCopy({
targets: [
{
src: "public/simulation/pFlowWeb.data",
dest: "src/wasm/internal:comlink:../webWorker/",
},
{
src: "public/simulation/pFlowWeb.wasm",
dest: "src/wasm/internal:comlink:../webWorker/",
},
],
}),
...