Monday, 12 April 2021

How to use a web-worker from an npm library into main webpack project

My project structure is like this:

moduleA -> Library that i publish to npm using Rollup

projectA -> My gatsby project that installs moduleA and uses it.

I'm using this library to bundle my workers with my other library code into the dist folder: https://github.com/darionco/rollup-plugin-web-worker-loader

Module A code:

workers/index.js

let webWorker = null;

if (typeof window !== "undefined") {
  webWorker = new Worker(new URL("./my.worker.js", import.meta.url), {
    type: "module",
  });
}

export default webWorker;

workers/my.worker.js

self.onmessage = (message) => {
  console.log("hii");
  self.postMessage("yes");
};

When I build the above library the result is this:

enter image description here

So you can see that the workers are correctly in the library's dist now. This all works great.

If we take a look into index.modern.module.js you can see this is the output for the worker code:

if (typeof window !== "undefined") {
  webWorker = new Worker(new URL("my.worker-f73c7cd4.js", import.meta.url), {
    type: "module"
  });
}

Now in my main project I have this webpack rule to convert the import.meta.url to a path otherwise webpack crashes as it does not recognize import.meta.url:

 config.module.rules.push({
  test: /\.jsx?$/,
  loader: require.resolve("@open-wc/webpack-import-meta-loader"),
});

I now run my main react project (which is built in gatsby & webpack) and this is the output in index.modern.module.js:

if (typeof window !== "undefined") {
  webWorker = new Worker(new URL("my.worker-8e6a623b.js", ({ url: getAbsoluteUrl('node_modules/@tracktak/dcf-react/dist/index.modern.module.js') }).url), {
    type: "module"
  });
}

Here's the network request, you can see it loans in but I'm pretty sure the path is wrong. It's just saying a 200 ok because it's going to 404 page I think:

enter image description here

And it gives me a console error:

Failed to load module script: The server responded with a non-JavaScript MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.

So, my question is. How do I load the web worker to the public folder for my Gatsby project (projectA). Do I need to use something like worker-loader here? I'm just not sure how it can work here because it's in my npm module and NOT in my project.

Any help would be great and I'd award a bounty!

Thanks

EDIT: It seems like worker-plugin is getting my closer to the solution. If I use this in my main project and modify the web workers in the dist output from this: new URL("my.worker-8e6a623b.js", ({ url: getAbsoluteUrl('node_modules/@tracktak/dcf-react/dist/index.modern.module.js') }).url) to this: new URL("my.worker-8e6a623b.js") it works fine as worker-plugin only accepts string arguments.

However this isn't a sustainable solution because obviously I don't want to modify dist files.



from How to use a web-worker from an npm library into main webpack project

No comments:

Post a Comment