[英]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.