Image for post
Image for post

Offline is becoming a standard thing to do in web applications because they allow your website to feel like an app. In the modern web most things are doable in an app can now be done on the web.

The progressive web app follows 3 principles:

  • Reliable — the application needs to load instantly and never show the offline dinosaur. The web application should be able to handle anything that is thrown at it so having a network fallback from the application is a must.

In this article, I am about to show you a game I built which helps you understand what it takes to get the bare minimum progressive web app out to production. A progressive web app could take a long time to build which can be a difficult type of ticket to get through the board.

So how can we breakdown the bare minimum which will still deliver value to the customer?

Step one — Setting up

Firstly, let’s clone down the repository on our local machines. All we have to do is run npm install and then npm run start-l1. The folder directory for lesson one is in /starter-files/lesson-1. The project will now spin up on localhost:8080.

Image for post
Image for post

Next we need to get setup on somewhere that will host our application. I have used Now — Zeit to host my web application in https. At some point we need to start deploying our application so we can see the experience on our own devices. It is really easy to get setup follow this guide to get setup.

Step Two — Build a manifest.json

This section will tick off the following in the lighthouse PWA checklist:

  • Sets an address-bar theme color

A web manifest provides the browser with information for the application for when the user installs the app onto their home screen.

Let’s go through what our manifest.json file needs:

  • The short_name is a string that represents the name of the web application displayed to the user if there is not enough space to display the full name.
Image for post
Image for post

Step Three — Offline Page

You made it this far! Awesome! Now we have done the easy part, let’s get into the nitty gritty part and make our web application have an offline page. Building an offline page requires us to build a service worker file.

A service worker file is a web worker which runs JavScript off the main thread. It has the power to cache files offline, proxy urls, push notifications and background syncs.

In the root of our project lets get a sw.js file made in the root of the project.

A service worker has three events which are; install, activate & fetch. These are the events which are more than likely in every service worker file as they are needed to make the service worker file install onto the users device.


The install phase is when the browser picks up the service worker and tries to install it on the device. The first thing we need to do is add a small snippet of JavaScript to our index.html file.

Image for post
Image for post

What is going on here is that we are checking if service worker is supported by the browser and then it will try and register the file. After that, we need to build our install event in the sw.js file.

Image for post
Image for post

In our example we have a variable called cacheFiles which has our offline page, main.js, style.css & our pwa-lighthouse.png image.

The few lines below are in there so we can have version control on our service worker cache. This will then allow us to be more efficient with what we cache and it stops us from having dead cache assets. If we have one cache number it will just make the cache go bigger and bigger until the cache can no longer save our assets.

In my example it is just a hard coded number but in a production projects we would have something like the build number in there or update the version when one of the assets in the cache has changed.

In the install event what is happening is that we wait until the caches API has opened and then it will add all of our cache files into the new cache instance.

Pro tip — the next then chain is not needed but it is very useful to use self.skipWaiting because it tells the service worker to not wait for the old service worker to unregister it will automatically install itself over the previous one.


The next thing we need to do to keep our cache file size low is to delete all of the of caches the service worker has previously added on the customers device.

Image for post
Image for post

First thing we need to do is make a cache whitelist array that will stop the cache API from deleting the cache we created in our install step. Once done, it will loop through all of the cache names and delete the other caches from the application cache.


The fetch event is fired when a network request is made. The service worker now listens to all of the fetch events so it can proxy the requests if we need to.

Image for post
Image for post

In our example, we need to determine which requests are html requests. We do not want to respond with an offline page when the request was not an html request.

If it is not an html request then we will check if that request exists in our cache and if it does, respond with the cached version on the service worker else it will fetch off for it if it does not exist in there.


Now we can test this out by turning off our network connection in dev tools. Go to devtools / network and then select the offline checkbox. This will emulate an offline experience.

Image for post
Image for post
Image for post
Image for post

We are offline! So we have now a manifest json file which tells our progressive web app how the app should work and then we added a service worker which will provide an offline page for our html requests. Now let’s get our application deployed to a production environment so we can fully test if our application is 100% PWA optimised.

Deploying the application

What we now need to do is run npm run deploy-l1 in our terminal. This will allow you to get access to the application on your phone and install it to your home screen. Let’s run a lighthouse test on our public domain.

Image for post
Image for post

We now have a fully working progressive web app.

As you can see, it doesn’t take much effort to get the bare minimum released to the user. Users can now start installing their applications on their devices and we can provide an offline page when the user has network difficulties.

Final Tips

  • utm_source=offline is a good way to track when a user comes back from the offline page to the current page on the site. This is a good way to get some metrics on which users converted when they returned.

Thank you for reading!

Advocate for Site Speed, PWA’s and Accessibility and UI Libraries

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store