Creating Custom Service Worker in React Apps

Learn to add custom service worker code in your react projects created using Create React App. The project code is available at GitHub

Full Transcript

Hello friends,

It's Harit from bonsaiilabs. Today I will show you how you can add custom service worker code in your react projects created using Create React App.

I have created a project using create-react-app and call it cra-custom-serviceworker. I have made changes to 2 files so let's view them first.

First, I have replaced the default implementation of App.js with my own implementation. This implementation contains 2 parts, a form and a userInfo in the table.

This form contains 1 text input and a button called Submit. I will shortly show you how this looks. When the user types into the box, handleChange method is called, which sets the value into the state. I have made use of React Hooks to keep the the state in the name variable whose default value is an empty string.

When a user clicks the Submit button, handleClick is called. It is logging a message on the console and I will soon call Github API to fetch the data and set the userInfo. The userInfo is then used in the render to present the information in the table.

I have also updated App.css to change the look and feel of the form. I have this app running locally, and we can see how it looks currently at http://localhost:3000. When I fill the my github username and click the button, a message is logged on the console as expected.

I will now change the implementation of handleClick. I will call fetch with the Github API and pass on the name provided by the user. I will call .then() method to capture response and return the result by calling json() method. I will use another .then() method and here I will have access to data returned by Github API. I will call the setUserInfo() method which will fill the userInfo object. Let's go back and test!

Back in the browser, I will refresh the page and enter my github username followed by clicking the button. As we can see, now the data is populated for my github username. I change the username to bonsaiilabs and the data renders the information for this user.

Now, let's say you want to intercept all the fetch() calls made to the network. Note that these fetch calls also include fetching resources such as icon files in your project. One way to do that is to use service worker and listen for the fetch event in your app. Let's see how to do that in a react app created using create-react-app

Back in our project, we can see a file called serviceWorker.js which comes with create-react-app. This file is NOT the service worker file, it is a template that will be used in the build process to create a service-worker file. I will show you a generated service worker file shortly. For now, this template file contains 2 methods called register(), and unregister(). These methods are used to register and unregister a service worker in the project. If you navigate to index.js, you'll see that currently service worker is not registered. Let's change this to register(), and see if service worker shows up.

Back in the browser, I hit refresh and navigate to Application Panel of Chrome Dev Tools, but we do not see the service worker here. That's because when you are using the app created with create-react-app, you must create a production build to see a registered service worker.

Back in the terminal, I will create a production build using npm run build. Once it completes, I will use serve -s build to serve the production bundle. Hmm, I do not have serve installed, so first I will install serve using npm install -g serve command. Once it completes, I will run serve -s build command and this time our app is running on port 5000 instead of 3000.

Back in the browser, I will change the port and here you see service worker with number 0 activated and running. And, our app is still running as expected.

Back in the codebase, the generated service worker file is created in build directory when I ran npm run build and it is called service-worker.js. If you look at the content of this file, you will see that is says it's an auto-generated file, and warns not to update it. Hmm, so where shall we write our service worker code to intercept fetch calls?

For that, I will create a new file under src directory, called custom-service-worker.js. In this file, I will add an eventlistener on self. Here self will refer to the service worker once this code is placed in our generated service worker file. I will show you how, in the next step. Here, I will called self.addEventListener() method and listen for fetch event, I will provide a callback which receives a fetch event, and with that event I log the request method and URL of the request.

Now, to include this code in our generated service-worker.js, I will change our build command located in package.json. I will append the contents of src/custom-service-worker.js to build/service-worker.js file. Then, I will create another production build by executing npm run build command, and run it using serve -s build command. We are now ready to test.

Back in the browser, I will first empty the cache and do a hard reload, but this did not load our new service worker changes, it is still sitting at number 0. I will try to reload few more times, before I see a message as below

New content is available and will be used when all tabs for this page are closed.

For that, I will open up a new tab, close the existing tab, and open out app at port 5000. As you can see, it started intercepting all the fetch requests. When I now enter github usernames and click submit, we can see the data, and that our custom service worker intercepts these fetch request as well.

Also, we can see our custom service worker code in the generated service-worker.js file as you navigate the build folder and scroll all the way at the bottom of the file.

Fantastic! so you now know how you can write a custom service worker with react projects created with create-react-app.

Let us know if you have more topics that you would like us to cover and we will work on them to help you learn better.

See you next time!