【问题标题】:Creating a web worker inside React在 React 中创建一个 web worker
【发布时间】:2018-05-08 14:12:24
【问题描述】:

我有一个使用 create-react-app 创建的 React 应用程序,但没有被弹出。我正在尝试使用网络工作者。我已经尝试过 worker-loader 包 (https://github.com/webpack-contrib/worker-loader)。

如果我尝试开箱即用的 worker-loader (import Worker from 'worker-loader!../workers/myworker.js';),我会收到错误消息,告诉我 Create React App 不支持 Webpack 加载器,我已经知道了。

解决方案是退出应用程序(我不想这样做)并编辑 webpack.config.js 还是有其他方法可以在 React 应用程序中使用网络工作者?

编辑:我在这里找到了解决方案:https://github.com/facebookincubator/create-react-app/issues/1277(由 yonatanmn 发布)

【问题讨论】:

    标签: reactjs webpack web-worker create-react-app


    【解决方案1】:

    正如我在上面问题的编辑中所写,我在这里找到了解决方案:https://github.com/facebookincubator/create-react-app/issues/1277

    这是一个工作示例:

    // worker.js
    const workercode = () => {
    
        self.onmessage = function(e) {
            console.log('Message received from main script');
            var workerResult = 'Received from main: ' + (e.data);
            console.log('Posting message back to main script');
            self.postMessage(workerResult);
        }
    };
    
    let code = workercode.toString();
    code = code.substring(code.indexOf("{")+1, code.lastIndexOf("}"));
    
    const blob = new Blob([code], {type: "application/javascript"});
    const worker_script = URL.createObjectURL(blob);
    
    module.exports = worker_script;
    

    然后,在需要使用web worker的文件中:

    import worker_script from './worker';
    var myWorker = new Worker(worker_script);
    
    myWorker.onmessage = (m) => {
        console.log("msg from worker: ", m.data);
    };
    myWorker.postMessage('im from main');
    

    【讨论】:

    • 问题是你不能将任何函数导入到blob中。
    • 意外使用 'self' no-restricted-globals
    【解决方案2】:

    是的,可以通过 custom-react-scripts 使用自定义 webpack 配置。

    要在您现有的create-react-app 项目中使用custom-react-scripts,如issue 中所述,您需要做的是:

    • 从 package.json 中移除反应脚本:

      "devDependencies": {
          "react-scripts": "0.6.1"
      },
      
    • 运行npm install --save-dev *your-custom-react-scripts*

    更详细的解释请看@kitze's article 和他自己的custom-react-scripts,其中包括对以下功能的内置支持:

    • 装饰器
    • babel-preset-stage-0
    • 萨斯
    • CSS 模块
    • Sass 模块
    • 更少的模块
    • 手写笔模块

    【讨论】:

    • 感谢您的提示。知道这样的事情是可能的很方便。与此同时,我找到了一个更简单的解决方案(请参阅我上面的编辑)。
    【解决方案3】:

    恭维 dnmh 的回答,this comment in the github issue 如果您遇到“this”、“self”、“window”主题的问题...

    在我的情况下,以下解决了我所有的麻烦:

    您无需触摸此文件,只需保留它即可。

    //WebWorkerEnabler.js
    export default class WebWorkerEnabler {
        constructor(worker) {
             let code = worker.toString();
             code = code.substring(code.indexOf("{") + 1, code.lastIndexOf("}"));
    
             const blob = new Blob([code], { type: "application/javascript" });
             return new Worker(URL.createObjectURL(blob));
        }
    }
    

    这是您运行后台任务的地方

    // WebWorker.js
    export default function WebWorker(args) {
        let onmessage = e => { // eslint-disable-line no-unused-vars
             // THIS IS THE PLACE YOU EMBED YOUR CODE THAT WILL RUN IN BACKGROUND        
             postMessage("Response");
        };
    }
    

    这是 WebWorker 与其余代码的连接。您从componentDidMountfunction 下方向 WebWorker 发送和接收数据。

    //BackgroundTaskRunner.js
    import * as React from 'react';
    import WebWorkerEnabler from './WebWorkerEnabler.js';
    import WebWorker from './WebWorker.js';
    const workerInstance = new WebWorkerEnabler(WebWorker);
    export default class BackgroundTaskRunner extends React.Component {
        componentDidMount(){
            workerInstance.addEventListener("message", e => {
                console.log("Received response:");
                console.log(e.data);
            }, false);
            workerInstance.postMessage("bar");
        }
        render() {
            return (
                    <React.Fragment>
                        {"DEFAULT TEXT"}
                    </React.Fragment>
            );
        }
    }
    

    【讨论】:

      【解决方案4】:

      按照这些步骤将您的工作人员文件添加到您的 create-react-app 项目中。

      1.安装这三个包:

      $ yarn add worker-plugin --dev
      $ yarn add comlink
      $ yarn add react-app-rewired --dev
      

      2。覆盖webpack 配置:

      在项目的root 目录中创建一个config-overrides.js 文件,其内容如下:

      const WorkerPlugin = require("worker-plugin");
      
      module.exports = function override(config, env) {
          //do stuff with the webpack config...
      
          config.plugins = [new WorkerPlugin({ globalObject: "this"}), ...config.plugins]
          return config;
      }
      
      

      3.将package.json 中的npm 脚​​本替换为:

      "start": "react-app-rewired start",
      "build": "react-app-rewired build",
      

      4.创建两个文件以测试您的配置:

      worker.js

      import * as Comlink from "comlink";
      
      class WorkerWorld {
        sayHello() {
          console.log("Hello! I am doing a heavy task.")
          let numbers = Array(500000).fill(5).map(num => num * 5);
          return numbers;
        }
      }
      
      Comlink.expose(WorkerWorld)
      

      use-worker.js

      import * as Comlink from "comlink";
      
      const initWorker = async () => {
          const workerFile = new Worker("./worker", { name: "my-worker", type: "module" });
          const WorkerClass = Comlink.wrap(workerFile)
      
          const instance = await new WorkerClass();
          const result = await instance.sayHello();
          console.log("Result of my worker's computation: ", result);
      }
      initWorker()
      

      5.查看输出:

      $ yarn start
      

      【讨论】:

        猜你喜欢
        • 2022-11-02
        • 1970-01-01
        • 1970-01-01
        • 2021-07-06
        • 2014-06-24
        • 2014-02-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多