简体   繁体   English

使用 Web Worker 和 React 和 Webpack 5

[英]Using Web Workers with React and Webpack 5

I have been trying to use Web Workers with react for a few days and I ran into a few issues.几天来,我一直在尝试使用 Web Workers 进行反应,但遇到了一些问题。

I started with a create-react-app using webpack 4. I could use a web worker using this tutorial: https://javascript.plainenglish.io/web-worker-in-react-9b2efafe309c which loads a WebWorker that way: I started with a create-react-app using webpack 4. I could use a web worker using this tutorial: https://javascript.plainenglish.io/web-worker-in-react-9b2efafe309c which loads a WebWorker that way:

export default class WorkerBuilder extends Worker {
  constructor(worker) {
    const code = worker.toString();
    const blob = new Blob([`(${code})()`]);
    return new Worker(URL.createObjectURL(blob));
  }
}

Unfortunately I need to use a lib from my worker (d3-delaunay) and webpack gave me an error when I tried to do so (I think it changed its path).不幸的是,我需要使用我的工作人员(d3-delaunay)的库,当我尝试这样做时,webpack 给了我一个错误(我认为它改变了它的路径)。

I heard about worker-loader and I learned that this had been deprecated since Web Worker importing is now built in webpack 5.我听说过 worker-loader 并且我了解到自从 Web Worker 导入现在内置于 webpack 5 以来,这已被弃用。

I updated my app to WebPack 5 (as explained in the create-react-app wiki), this was not easy since a lot of my dependencies broke.我将我的应用程序更新为 WebPack 5(如 create-react-app wiki 中所述),这并不容易,因为我的许多依赖项都损坏了。

But when I tried to load my WebWorker as explained here: https://webpack.js.org/guides/web-workers/ this didn't work at all (no errors).但是,当我尝试按照此处的说明加载 WebWorker 时: https://webpack.js.org/guides/web-workers/这根本不起作用(没有错误)。

That's my code:那是我的代码:

console.log("hello");
const worker = new Worker(new URL('./world.worker.js', import.meta.url));
worker.postMessage({
    question:
        'The Answer to the Ultimate Question of Life, The Universe, and Everything.',
});
worker.onmessage = ({ data: { answer } }) => {
    console.log(answer);
};
console.log("world");

And my world.worker.js:还有我的 world.worker.js:

import { Delaunay } from "d3-delaunay";

// eslint-disable-next-line import/no-anonymous-default-export
export default () => {
    // eslint-disable-next-line no-restricted-globals
    self.onmessage = (message) => {
        console.log("yolo");
    };
};

But my only output was:但我唯一的 output 是:

hello
world

My worker didn't seem to work.我的工人似乎没有工作。

I finally figured this out, I had the same issue.我终于想通了,我遇到了同样的问题。 The biggest issue is that you should not use export default in the web worker.最大的问题是您不应该在 web 工作程序中使用导出默认值。 Here is how I got it to work.这是我如何让它工作的。

You need to instantiate the worker using React.useMemo.您需要使用 React.useMemo 实例化工作人员。 This is so only one worker is created.这样就只创建了一个工人。

const worker = React.useMemo(() => new Worker(new URL('./world.worker.js', import.meta.url)), []);

To get the response, you need to know when the worker object is updated.要获得响应,您需要知道 worker object 何时更新。 To do this, you can use React.useEffect.为此,您可以使用 React.useEffect。

React.useEffect(() => {
  worker.onmessage = ({ data: { answer } }) => {
    console.log(answer);
    return () => worker.terminate();
  }
}, [worker]);

Finally, your world.worker.js file has two issues.最后,您的 world.worker.js 文件有两个问题。 The first one is that it doesn't actually return anything.第一个是它实际上并没有返回任何东西。 You will need to add a call to postMessage.您将需要添加对 postMessage 的调用。 The second issue which is the one I had trouble figuring out, is that you should not wrap the function in export default.我无法弄清楚的第二个问题是,您不应将 function 包装在导出默认值中。 I think this is because webpack will wrap it for you.我认为这是因为 webpack 会为您包装它。 See below for the correct world.worker.js code.请参阅下面的正确 world.worker.js 代码。

import { Delaunay } from "d3-delaunay";

self.onmessage = ({ data: { question } }) => {
  postMessage({
    answer: 42,
  });
};

to use es6 modules in workers, you need to load it in script mode using this syntax:要在 worker 中使用 es6 模块,您需要使用以下语法以脚本模式加载它:

new Worker('worker-path.js', {type: 'module'})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM