Den Dribbles

Prompting New App Versions With The Service Worker And Create-React-App

August 18, 2020

Service workers can a powerful utility to increasing performance in your app. They provide some powerful caching mechanisms and modern capabilities, however, they are generally misunderstood in web development.

A common misconception is that when new content is available, it will only be loaded once all tabs for your progressive web app are closed.

While this can be the default behaviour, you can speed this process up by skipping the wait and prompting the user to update.

In this short tutorial, we will do just that to a Create React App setup.

Creating the React App

We will used npx create-react-app and install Vercel’s serve globally to serve our build.

npx create-react-app hello-cra-push-notifications
cd hello-sw-push-notifications
# We'll use this to serve our app
npm i -g serve

Before building, let’s update index.js:

import React from "react"
import ReactDOM from "react-dom"
import "./index.css"
import App from "./App"
import * as serviceWorker from "./serviceWorker"

    <App />

// Changes made here
  onUpdate: registration => {
    const waitingServiceWorker = registration.waiting

    if (waitingServiceWorker) {
      waitingServiceWorker.addEventListener("statechange", event => {
        if ( === "activated") {
          if (
              "There is a new version of the app ready. Please reload to update."
          ) {
      waitingServiceWorker.postMessage({ type: "SKIP_WAITING" })

Here we are adding out magic code for the onUpdate handler that CRA provides for us out-of-the-box.

In this code, we will check if there is a service worker waiting from file changes. If so, we simply add an event for a state change and post a message to SKIP_WAITING.

Now, the next time we reload the app, we will be prompted with a confirm dialog to reload the page with our latest updates!

There is still the option for the user to deny the change if they wish.

Build and serve

Let’s get our build up and going:

yarn build
serve build

Now at port 5000 (or whatever you have), you will see the usual CRA basic that has been built.

Let’s make some changes and see our prompt in action!

Make changes to your React App

Update the app to have whatever you want. This can include changes to the styles, etc. (I have done this in my example image below).

import React from "react"
import logo from "./logo.svg"
import "./App.css"

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>Make changes</p>
          rel="noopener noreferrer"
          Learn React

export default App

Once you are happy, simply run yarn build.

Do this in another tab while the server is running. There is no real reason here other than to prevent yourself from second guessing why the changes are happening.

If you reload the React App on port 5000, after a few moments you’ll see the following show up in the console:

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

Console log informing that a new Service Worker is ready

In fact, that log is the precursor right before our custom onUpdate hook comes into play. At the same time you will have that window dialog show up on the screen:

Window dialog prompting to reload

If we accept (and you can cancel if you want), you will see our updated app!



Of course, you don’t have to use the window dialog. Once that notification comes through, you can do whatever your heart desires to let the user know that they can update their app on reload. In fact, you could be rude and just reload the page on them (although I wouldn’t!).

As a final note, this is supported in most major browsers but with the caveat that Safari iOS does not support this. The trade-off is your to make!

Resources and further reading

  1. Window Dialog
  2. Service Worker API
  3. Service Worker Post Message
  4. Service Worker Waiting Compatibility

Image credit: Clément H

Related Articles

December 09, 2020

See how you can dynamically create UIs based on React State using dynamic imports, Next.js 10 and React State

December 02, 2020

Have you ever wanted to build a UI Component Library with TypeScript and React? This blog post will take you through a straightforward set up that uses the bare minimum to get a working component library that you can re-use across your different React projects.

November 16, 2020

This post will go through a simple example of setting up simple authentication with a user and password to your Next.js website.

November 08, 2020

This blog post will explore the new Next.js Image component for an optimised image experience on the web.

November 08, 2020

This blog post will explore the new internationalised routing in Next.js 10 and how you can use this to your advantage with react-intl for React.js

November 07, 2020

Learn how to create a test Stripe example, update that example and deploy to Vercel for a Stripe payment gateway, React 17, TypeScript 4 and Next.js 10

November 06, 2020

See a roundup of my look into Vercel's new analytics feature that you can enable on a Vercel project and see how I used GTMetrix to help push some numbers.

November 05, 2020

Learn how to deploy the base Next.js 10 app with the Vercel CLI and/or the Vercel GitHub Integration

November 04, 2020

Learn how to export static HTML from a Nextjs 10 project to host

November 04, 2020

Use the TypeScript AWS CDK to deploy static sites to S3 with a CloudFront distribution and Route53 setup for a custom domain.

A personal blog on all things of interest. Written by Dennis O'Keeffe, Follow me on Twitter