Creating Custom Service Workers

Create-React-App’s default service worker is good for caching static assets, but we want to do much more than that. For that, we need to disregard the default service worker and create one of our own.

The simplest way to do that is to go to the public folder in our app’s directory and create a new service worker file. I am going to name it customWorker.js . For now, let’s add a simple console log to check if it works.

console.log("Hello World");

The React App is still going to choose its default service worker. To fix this, open the src/serviceworker.js and at line 34 you will find the following code:

window.addEventListener('load', () => {

const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;

Replace the service-worker.js with the name of our custom service worker.

Run yarn build and serve -s build again to create a new production build and serve it. Reopen the app on chrome and check the console to see if you get the Hello World message printed.

If you get any errors, try to unregister the service worker and reload the browser.

This is a very manual way of using custom service workers in our app. The drawback of this method is that our app can no longer use Workbox. Workbox provides us a with a lot of cool features so it would be better to be able to keep Workbox and create custom service workers. So lets undo all the changes that we made in this section and start over.

Now add a new developer dependency called react-app-rewired which will help us rewrite the webpack config and take be able to use the Workbox.

$ yarn add -D react-app-rewired

Then open the package.json file and rewrite the scripts as shown below:

"scripts": {

"start": "react-app-rewired start",

"build": "react-app-rewired build",

"test": "react-app-rewired test",

"eject": "react-app-rewired eject"

}

Then create a new file named config.js in the root of the project directory. We will import the workbox-webpack-plugin and map over all the plugins till we get to the GenerateSW plugin, which we will then replace with InjectManifest plugin from Workbox.

const WorkboxWebpackPlugin = require('workbox-webpack-plugin')

module.exports = function override(config, env) {

config.plugins = config.plugins.map(plugin => {

if(plugin.constructor.name === 'GenerateSW') {

return new WorkboxWebpackPlugin.InjectManifest({

swSrc: './src/sw.js',

swDest: 'service-worker.js'

})

}

return plugin

})

return config

}

We then need to create the sw.js file in the src folder. Inside, we will define the actual custom service worker. I will simply add a console log and call skipWaiting and clientsClaim , ensuring that the service worker gets installed on all the open clients.

console.log("Hello World")

workbox.skipWaiting()

workbox.clientsClaim()

Do not add the last two lines if you are going to write a complex service worker, which you probably are.