Create a Progressive Web App — A Quick Tutorial

This is a simple and minimal guide to build a progressive web app. Feel free to skip what you already know.
A PWA allows the visitors of your web site to install it as an app on their devices. Once installed, users will have an icon on the home screen to launch your web app, just like a native app.
Pros
- PWAs on smartphones greatly increase user interactions for your business. As of 2020, smartphones make up more than half of the Internet’s traffic and users spend 90% of their time on apps.
- PWAs can be a lot faster than web sites since they can cache resources like images, sounds, CSS for faster loading.
- Users will be able to use some functionalities of your app even if they are completely offline. E.g. Dinner menu if you are making a restaurant app.
- You can send notifications to your users to increase interactions. At the time of writing iOS support for this is yet to arrive.
- You can seamlessly update PWAs. Updates are installed in the background without the user’s involvement.
- You can use all the HTML 5 goodies: Web Payments, Bio Metric Authentication, WebRTC, WebSockets, WebGL, GeoLocation, WebAudio, Web Speech Recognition, WebVR and many more!
- You don’t need to pay and submit your PWA to an app store.
Cons
- You cannot force a user to install a PWA. The browser triggers the installation prompt and it is completely optional.
- A PWA can only be installed from a web site that uses HTTPS.
- It doesn’t suite if you want to write platform-specific apps and do low-level programming. (E.g. A file zipper, a wallpaper changer)
0. Prepare your web site
If you don’t have a web site, create the following index.html
and place image.gif next to it. Also, It’s better to have Visual Studio Code and Live Server Extension installed to follow up on this tutorial.
<html>
<body>
<h1>Meow</h1>
<img src="image.gif"/>
</body>
</html>
1. Creating webmanifest file
The webmanifest file describes your web app. Here you define its name, icons and many more. This information will be used when installing your PWA. Create your manifest.webmanifest
file as below, and update as needed:
{
"name": "My Progressive Web App",
"short_name": "My PWA",
"start_url": "./",
"display": "standalone",
"background_color": "red",
"theme_color": "red",
"description": "A dead simple progressive web app",
"icons": [
{
"src": "icon_192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icon_512.png",
"sizes": "512x512",
"type": "image/png"
} ]
}
- start_url — A URL to the page you land just after opening the app.
- display — Defines screen space reserved for the app.
- background_color — The color of the screen before your app loads.
- theme_color — Components outside the app will adapt this color when displaying your app
- icons — Launcher icons for your PWA. The given two sizes are recommended for Android.
NOTE: iOS Safari currently doesn’t obey this file. It thinks different!
2. Creating a basic Service Worker
Your heart keeps pumping blood whether you are awake or asleep. Similarly, a “Service Worker” for your app is a separate entity that keeps running in the background, regardless of you are using the app or not. So what does a Service Worker do?
- Fetch and show notifications form your site.
- Update the PWA seamlessly
- Act as a mini local server and let users work offline.
- Fetch new content from your site even before the user open the app
Your success depends on your understanding on Service Workers. First, lets see how they work.
The first visit
- The browser visits your web site for the very first time.
- The browser looks for a service worker file and then creates a new Service Worker dedicated to your web site. (This is called Service Worker Registration)
- Since this is a new Service Worker, the browser pushes the Service Worker to the
install
phase. Here the Service Worker is free to do whatever it wants including doing nothing. - After the
install
phase, the browser pushes the Service Worker toactivate
phase. This is the phase where your Service worker is ready to serve but it’s letting you do anything just before it starts. - Finally, the Service Worker starts. It does nothing for now.
- Next, the user closes the web page, but still, the service worker continues to breathe. That’s how their life is like. Born to do background tasks.
Prepare your almost empty Service Worker file sw.js
:
self.addEventListener( 'install', function (event) {})self.addEventListener( 'activate', function (event) {})self.addEventListener( 'fetch', function (event) {})
Every service worker MUST handle
install
,activate
andfetch
events. A Service worker without these three events has no purpose in its life
The fetch
event is called whenever your user makes a request. Here we have the power to let that request reach your web server, or stop that from happening and serve something else. For now let’s keep the event handlers empty and get the PWA up and running.
Have your index.html
load Service Worker by adding:
<script> navigator.serviceWorker.register('sw.js')</script>
Your bare bone PWA is now ready. Right-click on index.html
and open it with Live Server:

Then go to Chrome Developer Options (F12) > Application tab:

If you have done something wrong, you will be seeing it here. Go to the Service Workers section in sidebar:

Note the phase of the Service Worker is Running. Which means it has passed install
and activate
phases!
This doesn’t mean your PWA is installed. This only means that a Service Worker has been spawned for your site and ready to do background tasks. PWA installation is indicated somewhere else :

After the installation, you will get a launcher icon on your device to open the PWA. You can easily test this on your Android smartphone through Remote Debugging by plugging the phone to your PC.
Keep in mind that PWAs are installable only if they have HTTPS or run on localhost. In this case, forward one of your mobile’s localhost port to PC’s Visual Studio Code Live Server port:

This maps http://localhost:8080 on phone to http://localhost:5500 on PC.
The following visits to your site…
On subsequent visits to the web site, the browser checks whether the service worker file has been updated. If so, that indicates your PWA has been updated and the browser should install the updated version. However, the update will not be installed till the user close the app. Why?
Updating a PWA while it’s running can break the running app and cause bad user experiences. Hence, updating occurs the next time the user launches the app. At that point browser replaces the old Service worker with the new one. (There are ways to update a running app. I do not consider it as a good practice)
3. install, activate and fetch handlers
Now that you have a working PWA, you need to know how to make the best use of a Service Worker. We can make the Service Worker do many things in its handlers for the phases.
Install handler is used to cache the static assets such as images, style sheets in your web site. This will reduce the load on your server. You do not need to cache the manifest and service worker since the browser already stores them internally at installation.
Activate handler an opportunity for you to do something just before the Service Worker fires up. We usually clean up old cache files here.
Fetch handler acts as a tiny server. It decides whether a request is first served by the server or by local cache. The order depends on your requirements.
All above is somewhat common for every Service Worker. Therefore, here is a template you can use as your Service Worker. Feel free to change as needed:
Make sure to update the CACHE_VERSION every time you update a web page. Changing the CACHE_VERSION will change the Service Worker file. The existing PWA installations will identify the change and update themselves. Otherwise, they will be serving an outdated content to your users even if you have added fresh content to your site.
Don’t stop from here. Learn how you can send push notifications to your PWA installations!