Search code examples
javascriptreactjsweb-worker

How to use a local class in a Webworker with React?


I'm working on a webworker and want to use a local class. The worker is created and used in a React application with (mostly) standard Webpack setup. This is the essential code:

/* eslint-disable no-restricted-globals */
/* eslint-disable @typescript-eslint/explicit-function-return-type */
/* eslint-disable @typescript-eslint/explicit-member-accessibility */
/* eslint-disable no-eval */

class Executor {
    run(code) {
        let result = "";
        let isError = false;
        try {
            result = eval(code);
            if (typeof result === "object") {
                result = JSON.stringify(result);
            }
        } catch (error) {
            result = error.toString();
            isError = true;
        }

        return [result, isError];
    }
}

export default () => {
    try {
        const executor = new Executor();
    } catch (e) {
        console.log("Webworker startup error: " + e);
    }
};

and when I create the webworker:

public componentDidMount(): void {
    const code = runtime.toString();
    const blob = new Blob(["(" + code + ")()"]);
    this.worker = new Worker(URL.createObjectURL(blob));
    this.worker.onmessage = this.handleWorkerMessages;
}

I get the error:

Webworker startup error: ReferenceError: Executor is not defined

What else is required to make the webworker recognize that class?

I also tried to put the class into an external file and import it from there, however that only changed the error a little:

Webworker startup error: ReferenceError: _ScriptingExecutor__WEBPACK_IMPORTED_MODULE_0__ is not defined


Solution

  • To understand what's going on you have to look at the string which is generated from the imported module (right before it is converted to a Blob). It contains only the default exported code (i.e. the anonymous function). The class is not included and consequently, when you load the code into your worker it misses the class.

    So either do not use a module for the worker code or use the URL to the script and feed that to the worker.