Create a Progressive Web App with React and Register a Service Worker

Chris Achard
InstructorChris Achard
Share this video with your friends

Social Share Links

Send Tweet
Published 6 years ago
Updated 5 years ago

A Progressive Web App (PWA) can cache static assets, which allows an app to be rendered faster, and even allows it to operate offline!

We’ll start a new app with create-react-app, and enable the service worker by registering it in index.js. Then we’ll build and serve a production version of the app - and show that it can work offline by disabling the server and refreshing the tab.

Instructor: [00:00] Create a new app with Create React App, called Todo PWA. Then CD into the new directory and start the app with yarn start, which will automatically bring up the app in a new web browser.

[00:19] I have a basic web server prepared, which includes a simple express app that can serve a list of to-do items, allows you to make a new item and also to delete an item from the list. That is running on localhost port 4567.

[00:43] For the React app itself, I added Bootstrap, which will come from a CDN, and have put the entire to-do list app in app.js. In the browser, we have a working, regular to-do list app. This is just a regular web app so far.

[01:05] A progressive web app is enabled by a service worker, which we can see in index.js. Old versions of Create React App turned on the service worker by default. Starting with Create React App 2.0we have to manually enable the service worker by calling serviceWorker.register.

[01:23] By default, that uses a cache-first strategy to serve all of our assets generated by the react app. If we open serviceworker.js, we can look at the register function that we just called.

[01:36] One really important thing to notice is that the service worker only registers in production mode. You could change this file to work in dev mode too, but that's advised against in the documentation because of caching problems that can be frustrating during development.

[01:51] If you do decide to go that route, you'll also need to change the default serviceworker.js file name because of a default serviceworker.js file that is served from React scripts in development mode.

[02:04] Instead, we'll test the service worker by building a production version of the app with yarn build and then serve that production version with serve -s build and then open localhost port 5000, where we can see the app running.

[02:24] Since we've registered the service worker, if we refresh now and open the Chrome DevTools to the console, we can see the message from Workbox showing us that the pre-cache is responding to the static assets.

[02:39] In the Network tab, we can see that the JavaScript and SVG assets are all being served now by the service worker instead of by the dev server. Since they come directly from the cache, your entire app will load faster than if it required a network call for each of those assets, which is one of the primary benefits of registering the service worker.

[02:59] In fact, we can now actually turn off the app server. If we refresh the app in the browser, we can still see it. There's nothing serving on localhost port 5000, but the app still loads because the service worker has been registered and is serving a cached version of the production app assets.

[03:18] Notice though that the service worker is only serving the static assets. The to-do items are still being loaded from the network, from our express web server. If we turn that off as well and refresh now, the list of items won't load because it's still trying to make a network call for that.

[03:38] The default service worker implementation from Create React App will cache all the static assets, but not any of the dynamic network calls that your app makes.

Sam Huang
Sam Huang
~ 6 years ago

Hello, I'm unable to serve -s build to start localhost: 5000 Getting the below message:

/Users/sam/.rbenv/versions/2.4.4/lib/ruby/2.4.0/un.rb:63:in `block in setup': invalid option: -s (OptionParser::InvalidOption)

I tried uninstalling .rbenv all together but I couldn't get my head around this. Please advice.

Chris Achard
Chris Achardinstructor
~ 6 years ago

Ah - it looks like you have a ruby command also called "serve", which is conflicting with the npm serve command. There are two things you could do:

  1. Install serve globally with: "yarn global add serve". However! this would mean you can't use the ruby serve command - so this may not be what you want.

  2. Install server locally to the project with "yarn add --dev serve". Then, to start the server, you can run: "./node_modules/serve/bin/serve.js -s build"

Option #2 may be better for your situation, so that you don't conflict with your existing ruby command.

Sam Huang
Sam Huang
~ 6 years ago

thank you so much! It solved the problem beautifully. Now I can go on and finish this course :D

Chris Achard
Chris Achardinstructor
~ 6 years ago

Great! Glad it helped.

Trung Hoang
Trung Hoang
~ 6 years ago

Hi, I am trying to follow your course but got stuck at express server setup. Do you have an instruction? Thanks.(Also my system doesn't have nodemon.)

Chris Achard
Chris Achardinstructor
~ 6 years ago

Sure, follow these instructions to get it working:

  • git clone the repo at https://github.com/nanohop/todo-pwa/tree/register-service-worker
  • cd into the server directory
  • run "npm install" to install express
  • run the server with "node server.js"

I was using nodemon because I was doing development on the server, and nodemon will automatically restart the server whenever you change the server.js file - but to just run the server, you don't need nodemon, you can use node directly.

Hope that helps!

Alexander Esser
Alexander Esser
~ 6 years ago

I had problems running serve -s build. It may have been related to https://github.com/zeit/serve/issues/382. Anyhow adding serve as dev dependency and putting "serve": "node .\\node_modules\\serve\\bin\\serve.js -s build" into "scripts" in packages.json on my Windows machine fixed it.

Rajender Joshi
Rajender Joshi
~ 5 years ago

In the transcript there is a typo, the code snippet mentions index.js but it should be App.js

Stephen
Stephen
~ 5 years ago

I'm wrestling with the setup and though I have the app running and server -s build working, it fails to find items.json which I'm not seeing in either of the two repos mentioned here: https://github.com/eggheadio-projects/progressive-web-apps-in-react-with-create-react-app/tree/master/lessons/02-create-a-progressive-web-app-with-react-and-register-a-service-worker or https://github.com/nanohop/todo-pwa/tree/register-service-worker

Chris Achard
Chris Achardinstructor
~ 5 years ago

@Stephen - the items.json are served by the server.js file located here: https://github.com/nanohop/todo-pwa/tree/master/server

(It's not a static file that gets served - it's dynamic from the express app there). Let me know if you have trouble with that!

Alex Parra
Alex Parra
~ 5 years ago

Regarding the serve -s build not working, what I did was add the following to scripts of package.json:

  "serve": "serve -s build",`

And run it with yarn serve.

Markdown supported.
Become a member to join the discussionEnroll Today