简体   繁体   English

Web 在 React 中导入模块的工人

[英]Web Worker with imported modules in React

I'm trying to make a web worker to prevent stalling the React main thread.我正在尝试创建一个 web worker 来防止 React 主线程停滞。 The worker is supposed to read an image and do various things.工人应该阅读图像并做各种事情。

The app was created using create-react-app .该应用程序是使用create-react-app

Currently I have目前我有

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 component AppContent.js I have import WebWorker from "./workers/WebWorker";然后在我的 React 组件AppContent.js中,我从“./workers/WebWorker”导入了 WebWorker; import readImageWorker from './workers/readimage.worker.js';从 './workers/readimage.worker.js' 导入 readImageWorker;

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 component
    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___default is not defined未捕获的 ReferenceError:未定义 jimp__WEBPACK_IMPORTED_MODULE_0___default

How can I properly import a module into a web worker?如何将模块正确导入 web worker?

EDIT:编辑:

As per suggestions from Kaiido, I have tried installing worker-loader , and edited my webpack.config.js to the following:根据 Kaiido 的建议,我尝试安装worker-loader ,并将我的 webpack.config.js 编辑为以下内容:

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

But when I run it, I still get the error但是当我运行它时,我仍然得到错误

Uncaught ReferenceError: jimp__WEBPACK_IMPORTED_MODULE_0__ is not defined未捕获的 ReferenceError:未定义 jimp__WEBPACK_IMPORTED_MODULE_0__

I experienced the same problem.我遇到了同样的问题。 Firefox could not show me where exactly the error was (in fact it was plain misleading...) but Chrome did. Firefox 无法告诉我错误的确切位置(事实上,这很容易误导......)但 Chrome 做到了。 I fixed my problem by not relying on an import statement (importing one of my other files) which would only have worked within a React context.我通过不依赖只能在 React 上下文中工作的导入语句(导入我的其他文件之一)来解决我的问题。 When you load a Worker script (via the blob() / URL() hack), it has no React context (as it is loaded at runtime and not at transpile time).当你加载一个 Worker 脚本时(通过 blob() / URL() hack),它没有 React 上下文(因为它是在运行时加载的,而不是在转译时加载的)。 So all the React paraphernalia __WEBPACK__blah_blah is not going to exist / be visible.所以所有 React 工具 __WEBPACK__blah_blah 都不会存在/可见。 So... within react... import statements in worker files will not work.所以...在反应中...工作文件中的导入语句将不起作用。 I haven't thought of a workaround yet.我还没有想到解决方法。

I'm not too much into React, so I can't tell if the module-Worker is the best way to go (maybe worker-loader would be a better solution), but regarding the last error you got, it's because you didn't set the type of your Blob when you built it.我不太喜欢 React,所以我不知道 module-Worker 是否是 go 的最佳方式(也许worker-loader会是更好的解决方案),但关于你得到的最后一个错误,这是因为你没有不要在构建 Blob 时设置它的type

In this case, it does matter, because it will determine the Content-Type the browser sets when serving it to the APIs that fetch it.在这种情况下,它确实很重要,因为它将确定浏览器在将其提供给获取它的 API 时设置的 Content-Type。
Here Firefox is a bit more lenient and somehow allows it, but Chrome is picky and requires you set this type option to one of the many javascript MIME-types.这里 Firefox 稍微宽松一点,并且以某种方式允许它,但 Chrome 很挑剔,需要您将此type选项设置为众多 javascript MIME 类型之一。

 const script_content = `postMessage('running');`; // this one will fail in Chrome const blob1 = new Blob([script_content]); // no type option const worker1 = new Worker(URL.createObjectURL(blob1), { type: 'module'}); worker1.onerror = (evt) => console.log( 'worker-1 failed' ); worker1.onmessage = (evt) => console.log( 'worker-1', evt.data ); // this one works in Chrome const blob2 = new Blob([script_content], { type: "text/javascript" }); const worker2 = new Worker(URL.createObjectURL(blob2), { type: 'module'}); worker2.onerror = (evt) => console.log( 'worker-2 failed' ); worker2.onmessage = (evt) => console.log( 'worker-2', evt.data );

But now that this error is fixed, you'll face an other error, because the format import lib from "libraryname" is still not supported in browsers, so you'd have to change "libraryname" to the path to your actual script file, keeping in mind that it will be relative to your Worker's base URI, ie probably your main-page's origin.但是现在这个错误已经修复了,你会遇到另一个错误,因为import lib from "libraryname"在浏览器中仍然不支持,所以你必须将"libraryname"更改为你的实际脚本文件的路径, 请记住,它将与您的 Worker 的基本 URI 相关,即可能是您的主页的来源。

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

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