admin管理员组

文章数量:1415139

I'm trying to make a web worker to prevent stalling the React main thread. The worker is supposed to read an image and do various things.

The app was created using create-react-app.

Currently I have

webpack.config.js

module.exports = {
    module: {
        rules: [
            {
                test: /\.worker\.js$/,
                use: { loader: 'worker-loader' }
            }
        ]
    }
};

WebWorker.js

export default class WebWorker {
    constructor(worker) {
        const code = worker.toString();
        const blob = new Blob(['('+code+')()'], {type: "text/javascript"});
        return new Worker(URL.createObjectURL(blob),  {type: 'module'});
    }
}

readimage.worker.js

import Jimp from "jimp";

export default () => {
    self.addEventListener('message', e => { // eslint-disable-line no-restricted-globals
        if (!e) return;
        console.log('Worker reading pixels for url', e.data);
        let data = {};

        Jimp.read(e.data).then(image => {
            // jimp does stuff
            console.log('Worker Finished processing image');
        })

        postMessage(data);
    })
};

And then in my React ponent AppContent.js I have

import WebWorker from "./workers/WebWorker";
import readImageWorker from './workers/readimage.worker.js';

export default function AppContent() {
    const readWorker = new ReadImageWorker(readImageWorker);
    readWorker.addEventListener('message', event => {
        console.log('returned data', event.data);
        setState(data);
    });

    // callback that is executed onClick from a button ponent
    const readImageContents = (url) => {
        readWorker.postMessage(url);
        console.log('finished reading pixels');
    };
}

But when I run it, I get the error

Uncaught ReferenceError: jimp__WEBPACK_IMPORTED_MODULE_0__ is not defined

How can I properly import a module into a web worker?

I'm trying to make a web worker to prevent stalling the React main thread. The worker is supposed to read an image and do various things.

The app was created using create-react-app.

Currently I have

webpack.config.js

module.exports = {
    module: {
        rules: [
            {
                test: /\.worker\.js$/,
                use: { loader: 'worker-loader' }
            }
        ]
    }
};

WebWorker.js

export default class WebWorker {
    constructor(worker) {
        const code = worker.toString();
        const blob = new Blob(['('+code+')()'], {type: "text/javascript"});
        return new Worker(URL.createObjectURL(blob),  {type: 'module'});
    }
}

readimage.worker.js

import Jimp from "jimp";

export default () => {
    self.addEventListener('message', e => { // eslint-disable-line no-restricted-globals
        if (!e) return;
        console.log('Worker reading pixels for url', e.data);
        let data = {};

        Jimp.read(e.data).then(image => {
            // jimp does stuff
            console.log('Worker Finished processing image');
        })

        postMessage(data);
    })
};

And then in my React ponent AppContent.js I have

import WebWorker from "./workers/WebWorker";
import readImageWorker from './workers/readimage.worker.js';

export default function AppContent() {
    const readWorker = new ReadImageWorker(readImageWorker);
    readWorker.addEventListener('message', event => {
        console.log('returned data', event.data);
        setState(data);
    });

    // callback that is executed onClick from a button ponent
    const readImageContents = (url) => {
        readWorker.postMessage(url);
        console.log('finished reading pixels');
    };
}

But when I run it, I get the error

Uncaught ReferenceError: jimp__WEBPACK_IMPORTED_MODULE_0__ is not defined

How can I properly import a module into a web worker?

Share Improve this question asked Apr 9, 2020 at 4:49 cclloydcclloyd 9,25518 gold badges68 silver badges122 bronze badges 3
  • import in workers is not widely supported yet - looks like Chrome, Edge, and node right now, developer.mozilla/en-US/docs/Web/JavaScript/Reference/…. have you tried importScripts? developer.mozilla/en-US/docs/Web/API/Web_Workers_API/… – James South Commented Apr 9, 2020 at 5:43
  • @JamesSouth I looked at using importScripts, but besides it gives a linting error (which I can set to ignore), where am I supposed to import the module from? I can't use the relative path in the node_modules folder, nor just jimp. The only way to use importScripts with it is to copy the module to the public folder and then use an absolute url (such as http://localhost:3000/jimp.js). Is there a better way to do that? – cclloyd Commented Apr 9, 2020 at 9:52
  • 2 Maybe worker-plugin github./GoogleChromeLabs/worker-plugin instead of worker-loader would help?? – James South Commented Apr 9, 2020 at 21:15
Add a ment  | 

2 Answers 2

Reset to default 1

You might have a problem with webpack importing your worker in the WebWorker class. Try returning new Worker(URL.createObjectURL(blob), import.meta.url)); like how it's documented in the webpack docs.

In my next.js typescript project, I use this code and answer in my use case:

  • function in onClick prop on the element at next.js
async () => {
  const testWorker = new Worker(
    new URL("./test.worker.ts", import.meta.url), {
      name: "test",
      type: "module",
    });
  testWorker.onmessage = function (event) {
    console.log("data:", event.data, "\n", "event:", event);
  };

  testWorker.postMessage([0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
}


  • test.worker.ts
self.onmessage = function ({ data }) {
  self.postMessage((data as number[]).map((d) => d * 10));
};

export {};

本文标签: