web-dev-qa-db-ja.com

React内にWebワーカーを作成する

Reactアプリがcreate-react-appで作成され、イジェクトされていません。Webワーカーを使用しようとしています。ワーカーローダーパッケージを試してみました( https: //github.com/webpack-contrib/worker-loader )。

箱から取り出してワーカーローダーを試してみると(import Worker from 'worker-loader!../workers/myworker.js';)、WebpackローダーはCreate React Appでサポートされていないことを既に知っています。

解決策は、アプリをイジェクトして(私はしたくない)Webpack.config.jsを編集することですか、またはReactアプリ内でWebワーカーを使用する他の方法がありますか?

編集:ここで解決策を見つけました: https://github.com/facebookincubator/create-react-app/issues/1277 (yonatanmnによる投稿)

8
dnmh

上記の私の質問の編集で書いたように、私はここで解決策を見つけました: 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ワーカーを使用する必要があるファイルで次のようにします。

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');
14
dnmh

はい、custom-react-scriptsを使用してカスタムWebpack構成を使用することが可能です。

この issue で説明されているように、既存のcustom-react-scriptsプロジェクトでcreate-react-appを使用するには、次のことを行う必要があります。

  • Removereact-scriptsをpackage.jsonから削除します:

    "devDependencies": {
        "react-scripts": "0.6.1"
    },
    
  • npm install --save-dev *your-custom-react-scripts*を実行します

詳細な説明については、次のような機能の組み込みサポートを含む @ kitzeの記事 と彼自身の custom-react-scripts をご覧ください。

  • デコレータ
  • babel-preset-stage-0
  • もっと少なく
  • サス
  • CSSモジュール
  • Sassモジュール
  • より少ないモジュール
  • スタイラスモジュール
2
otorrillas

Dnmhの回答を補完する githubの問題のこのコメント 「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>
        );
    }
}
0
Mehmet Kaplan