Use a Custom Service Worker in a create-react-app PWA without Ejecting

Chris Achard
InstructorChris Achard
Share this video with your friends

Social Share Links

Send Tweet
Published 6 years ago
Updated 5 years ago

The default service worker that comes with create-react-app doesn't allow for very much configuration. We'll replace that default service worker in two ways.

First, we'll create a blank service worker js file, and use that as our custom service worker.

Next, we'll re-write the default webpack config with react-app-rewired, and utilize the InjectManifest workbox webpack plugin. This will allow us to create a totally custom service worker that still allows us to use workbox, without ejecting our app.

Instructor: [00:00] The most basic way to replace the default service worker is to make a new file in the public folder and we'll call that myserviceworker.js. That name could be anything you'd like, but the file must be in the root of the public folder, so that it can be served from the root of our application.

[00:19] Let's just add a console.log line here. Then open serviceworker.js. There we can find the old service worker file name and replace it with our new service worker file name. Again, it's important that we serve from the root here because the service worker can only control the parts of the app that are at the same level or below the level that it's served from.

[00:44] Then we can make a new production build and serve it and open it in Chrome. In the console tab we can see our "Hello" message, so we know the service worker is running. Also, in the application tab of Chrome's DevTools we can see the new service worker file name. If we click on it we can see our custom service worker.

[01:07] That's the easiest way to replace the service worker, but it totally bypasses Workbox, which has a lot of functionality that we want to take advantage of for this application. Let's revert back to the original file name and delete the custom service worker.

[01:22] In terminal install react-app-rewired, which we can use to rewrite the webpack config without ejecting and take full advantage of Workbox. Make a new file called config-overides.js in the root of the project. We'll copy in the default function from the react-app-rewired's documentation.

[01:44] To see what we're working with, we can log the config here. Then comment out the return, which will help the webpack process and let us see the config. Next open package.json in the root of the project and replace the default react-script-calls with react-app-rewired for start, build, and test.

[02:08] Now let's make a production build, which shows us the config that we're working with, and then stops the build process. The basic service worker is currently being generated by this Generate SW plugin. That's the plugin that we want to replace with a more fully featured Workbox plugin.

[02:27] In config-overides.js we can import Workbox, and then map over all the plugins. When we get to the Generate SW plugin, we'll replace it with InjectManifest from Workbox. We can name the source whatever we'd like. We'll call that sw.js and put it in the source folder. The destination has to match what we have in serviceworker.js. We'll call that service¬-worker.js.

[03:07] Now we can make the new sw.js file in source. Here we can define our custom service worker. As for the console log like before, but we can also use all the power of Workbox. For this example, we'll call Skip Waiting and Client's Claim, which will ensure our service worker gets installed on all the open clients right away.

[03:30] If your service worker is complex you probably don't want these two lines, but they're useful for this demo. Finally, we can build a new build and serve it. Then open a new tab and navigate to it in Chrome. In the console we see our message. Then in the application tab we can see the generated service worker code and we can see that Workbox is properly setup and working.

Alexander Esser
Alexander Esser
~ 6 years ago

NB; This code might/will fail when using react-scripts > 2.1.1 (https://github.com/timarney/react-app-rewired/issues/343)

Alexander Esser
Alexander Esser
~ 6 years ago

NB: This code will fail when using react-scripts higher 2.1.1 (https://github.com/timarney/react-app-rewired/issues/343)

OndeVai
OndeVai
~ 6 years ago

I got it to work using Craco (https://github.com/sharegate/craco/blob/master/packages/craco/README.md):

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

module.exports = { webpack: { alias: {}, plugins: [], configure: (webpackConfig, other) => { ///console.log('----crackass webpackConfig', webpackConfig) webpackConfig.plugins = webpackConfig.plugins.map(plugin => { if (plugin.constructor.name === 'GenerateSW') { return new WorkboxWebpackPlugin.InjectManifest({ swSrc: './src/sw.js', swDest: 'service-worker.js' }) } return plugin }) return webpackConfig } } }

Andre Souza
Andre Souza
~ 5 years ago

New versions of creat-react-app will have the funcrtions skipWaiting and clientsClaim in the core package so instead of workbox.skipWaiting() use workbox.core.skipWaiting()

by Ernesto

Sebastian Ricarde
Sebastian Ricarde
~ 5 years ago

New versions of creat-react-app will have the funcrtions skipWaiting and clientsClaim in the core package so instead of workbox.skipWaiting() use workbox.core.skipWaiting()

by Ernesto

Thank you 👌

Héctor BlisS
Héctor BlisS
~ 5 years ago

New versions of creat-react-app will have the funcrtions skipWaiting and clientsClaim in the core package so instead of workbox.skipWaiting() use workbox.core.skipWaiting()

by Ernesto

Muchas gracias!

Markdown supported.
Become a member to join the discussionEnroll Today