How to use web workers with react-create-app and not ejecting in the attempt
Last week, my coworkers and I were working in an app that needeed some considerebly heavy process that we thought shouldn’t run on the main thread. So because of performance concerns, we decided to put this heavy code in a web workers. Everything was great until we decided to build into the production environment…
It turns out that apps made with CRA (create-react-app) have no “native” support for Web Workers, so it just didn’t work when built into production. That lead us to try (very hard) to find a way to make this work.
After a while trying…
We found a way to make it run with a webpack loader called Worker-Loader, it was hard to understand because, frankly speaking, none of us had manipulated webpack before, but after a time reading around, we finally understood how it work; everything was just glorious…
Until we noticed that running the loader inline (meaning that it runs inside the import statement), is not allowed in react, so the only way to make it works was modifying the web-pack.config file… Hang on! what web-pack.config file?!, well the file you only get by ejecting your app!
OK, but what’s the problem with that? You may be asking. By doing so, there are two major issues: The first one is that if you eject your app, you get access to everything, and I mean EVERYTHING, in your app configuration, so if you make something wrong you could break your app in a serious way, that’s why they warn you by ejecting your app you’re on your own and there’s nothing they can help in case you brake something.
The second problem comes if you’re working with git. By ejecting your app, you have to drop your current git configuration and re-build it again after the eject. A thing we definitely didn’t want to do.
React App Rewired to the rescue!
Finally, we found this really cool library called React App Rewired that lets you modify your Webpack config without ejecting your app, and after some reading we made it work, and not ejecting in the attempt!
Cutting to the chase…
The Dependencies you’ll need
Worker-Loader and React Rewired App. You can get them by typing this in your command line:
npm install react-app-rewired worker-loader --save-dev
Now, let’s create a test Web Worker and implement it in the component we want
This is a simple web worker file, and it will help us to make sure everything goes fine
Now, implement it by importing it and creating a new instance of it this way…
Notice that my web worker file ends with a “.worker.js”. This is very important since it will help us at the time of implementing the loader we need (worker-loader) into our webpack.config file with react-app-rewired
Setting up Web pack through React-App-Rewired
OK, What we need to do is modify the web-pack.config file without “touch it”. To do this, we need to create a file at the root level of the project (the very same level your package.json and your src folder are, for instance) and name it “config-overrides.js”. This file is what allows react-app-rewired modifies the webpack.config file
I want you to pay attention to the line “test: /\.worker\.js$/”, well, that regular expression tells the loader to take every file ending with a .worker.js and makes it work like a worker, so that’s why I told you to name all your web workers ending like that.
Finally, we need to go to our package.json file and change some scripts in order to call react-app-rewired.
And that’s it! your web worker should work just fine, in both, development and production environment.
In order to test it I put my state’s counter property (in App.js file) into the view and the counter made with Web Worker updates just fine! :D
I hope this helps all of you a lot and makes your web workers… work