Search code examples
javascriptwebpackimportmoduleweb-worker

Pass a function to a web worker that uses a webpack imported class


I want to pass a simple function to a web worker, rather than writing it directly in the web worker. I know this isn't directly possible, but that you can "work around" this in many cases by calling toString() on your function and calling eval on that string, once it's in the worker.

The caveat that I haven't seen addressed elsewhere is that this function uses a class imported from another module. (I am using webpack.)

Take this function: () => new MyClass();

Calling toString() on it gives this:

() => {
  return new _MyClass__WEBPACK_IMPORTED_MODULE_5__["MyClass"]();
}

That makes sense, as MyClass is imported from another module. The problem is that calling eval on this in the worker gives an error:

ReferenceError: _MyClass__WEBPACK_IMPORTED_MODULE_5__ is not defined

Again, that makes sense, because the class wasn't imported in the worker's module. But is there any way I can work around this? The class referenced by the function won't be known at the time that the worker is written.

Unsurprisingly, I get this result whether using worker-loader or creating the worker with an object URL like this:

new Worker(URL.createObjectURL(new Blob([functionString])));

I've tried using dynamic imports inside the function I pass into the worker, but this still fails as seemingly the worker doesn't expect to be doing dynamic import:

() => {
  return import ('./MyClass')
    .then(module => new module.MyClass());
}

ReferenceError: __webpack_require__ is not defined

Is there any clever way to work around this, or should I give up and expect to write a different worker for every class I want to instantiate?


Solution

  • I've come to the conclusion that this can't be done in a robust and non-hacky manner, though I'm happy to be proven wrong still.

    I'll use a different worker for each class I want to instantiate, at least for now.