I have a React app created with create-react-app, not ejected. I\'m trying to use web workers. I\'ve tried the worker-loader package (https://github.com/webpack-contrib/work
Yes, it is possible to use custom webpack config through using custom-react-scripts
.
To use custom-react-scripts
in your existing create-react-app
project, as explained in this issue, what you need to do is:
Remove react-scripts from package.json:
"devDependencies": {
"react-scripts": "0.6.1"
},
Run npm install --save-dev *your-custom-react-scripts*
For a more detailed explanation, have a look at @kitze's article and his own custom-react-scripts, that include built-in support for features like:
Complimenting dnmh's answer, this comment in the github issue works perfect if you are experiencing problems with "this", "self", "window" subjects...
In my case following solved all my troubles:
You don't need to touch this file, just keep it.
//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));
}
}
This is where you run your background tasks
// 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");
};
}
And here is the connection of WebWorker with the rest of your code. You send and receive data to WebWorker from below componentDidMount
function.
//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>
);
}
}
As I've written in the EDIT of my question above, I've found the solution here: https://github.com/facebookincubator/create-react-app/issues/1277
This is a working example:
// 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;
Then, in the file that needs to use the 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');