web-dev-qa-db-fra.com

Créer un travailleur Web à l'intérieur React

J'ai une application React créée avec create-react-app, non éjectée. J'essaie d'utiliser des travailleurs Web. J'ai essayé le package travailleur-chargeur ( https: //github.com/webpack-contrib/worker-loader ).

Si j'essaie travailleur-chargeur hors de la boîte (import Worker from 'worker-loader!../workers/myworker.js';), J'obtiens un message d'erreur m'informant que les chargeurs Webpack ne sont pas pris en charge par Create React App, que je connais déjà.

La solution consisterait-elle à éjecter l'application (ce que je préférerais ne pas faire) et à modifier le webpack.config.js ou existe-t-il une autre manière d'utiliser les travailleurs Web dans une application React?

EDIT: J'ai trouvé la solution ici: https://github.com/facebookincubator/create-react-app/issues/1277 (post par yonatanmn)

8
dnmh

Comme je l'ai écrit dans l'EDIT de ma question ci-dessus, j'ai trouvé la solution ici: https://github.com/facebookincubator/create-react-app/issues/1277

Ceci est un exemple de travail:

// 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;

Ensuite, dans le fichier qui doit utiliser le 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');
14
dnmh

Oui, il est possible d'utiliser une configuration de webpack personnalisée en utilisant custom-react-scripts.

Utiliser custom-react-scripts dans votre create-react-app projet, comme expliqué dans ce issue , ce que vous devez faire est:

  • Supprimer react-scripts de package.json:

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

Pour une explication plus détaillée, consultez article de @ kitze et le sien custom-react-scripts , qui inclut la prise en charge intégrée de fonctionnalités telles que:

  • Décorateurs
  • babel-preset-stage-0
  • Moins
  • Toupet
  • Modules CSS
  • Modules Sass
  • Moins de modules
  • Modules de stylet
2
otorrillas

Complimentant la réponse de dnmh, ce commentaire dans le numéro de github fonctionne parfaitement si vous rencontrez des problèmes avec les sujets "this", "self", "window" ...

Dans mon cas, la suite a résolu tous mes problèmes:

Vous n'avez pas besoin de toucher ce fichier, conservez-le.

//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));
    }
}

C'est là que vous exécutez vos tâches d'arrière-plan

// 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");
    };
}

Et voici la connexion de WebWorker avec le reste de votre code. Vous envoyez et recevez des données vers WebWorker par le dessous de la fonction componentDidMount.

//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