Converting Existing React App to PWA

Agne Urbaityte
The Startup
Published in
5 min readDec 5, 2020

You are in the middle of working on your React App and suddenly hear that there is one cool thing called PWA that can do cool stuff. You get excited and decide to convert your web application into PWA. Been there, done that. But let’s start from the beginning: what is it and why to build them?

What is PWA?

Progressive Web Application (PWA) is a combination of the best web and mobile application features. After integrating service workers and a manifest file, your web application becomes installable and reliable. Steve Jobs was the first to present the concept to the world during the iPhone launch in 2007. It needed 8 years to evolve from the idea to a real, functional term, and in 2015 PWA was introduced to the market by Google.

Why do we need Progressive Web Applications?

PWA makes your site:

  • More reliable and faster — service worker caches your content and does predictive prefetching.
  • Installable — users can access it from their home screen or app launcher.
  • Indexable and linkable — your app is visible in the browsers, searchable for users.

Let’s talk examples:

  • Twitter: launching its PWA in 2017 resulted in a 65% increase in pages per session, a 75% increase in Tweets sent, and a 20% lower bounce rate.
  • Pinterest: built a PWA when they discovered that their website experience is too slow. On Pinterest’s PWA, users spend 40% more time compared to the previous version. It’s PWA requires only 150 KB of data storage.
  • Starbucks: introducing it’s PWA in 2017 resulted in a 2x increase in their daily active users. Their PWA takes up 233 KB of data storage.
  • Forbes: their rebranded mobile experience with PWA brought 43% more sessions per user and a 20% increase in ad viewability.

Okay, we understood all the benefits and would love to move to the coding part. With the guidance and all the steps below, you should be able to convert your web app into PWA. We will make sure of that by running the Lighthouse report at the end.

1st step — creating a service worker

Wait…But what is a service worker? The easiest way to think about it as a JavaScript file running separately from the main browser thread, intercepting network requests and caching or retrieving resources from the cache.

Let’s create an empty file called serviceWorker.js in the folder where your index.html lives. In your index.html, add a script in <body>:

<script>if (‘serviceWorker’ in navigator) {window.addEventListener(‘load’, function() {navigator.serviceWorker.register(‘serviceWorker.js’).then(function(registration) {// Registration was successfulconsole.log(‘ServiceWorker registration successful with scope: ‘, registration.scope);}, function(err) {// registration failed :(console.log(‘ServiceWorker registration failed: ‘, err);});});}</script>

Run the server and take a look at the console in Chrome browser’s DevTools. You should see something similar to the following:

Also, click on the Application tab, where you should see more detailed information about the registered service worker.

2nd step — installing a service worker

The registration process is kicked off, and we can move on to the service worker script, which manages the install event.

In serviceWorker.js, we need to define a callback for the install event and choose what to cache. Inside the callback, we have to open a cache, cache the files, and get confirmation that assets are cached. serviceWorker.js can look like this:

let CACHE_NAME = ‘my-site-cache-v1’;
const urlsToCache = [
‘/’,
‘/index.html’,
];
self.addEventListener(‘install’, function(event) {
// Perform install steps
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
console.log(‘Opened cache’);
return cache.addAll(urlsToCache);
})
);
});

We also want to inform service workers what to do with the cached files. This will be done with the fetch event.

self.addEventListener(‘fetch’, function(event) {event.respondWith(caches.match(event.request).then(function(response) {if (response) {return response;}return fetch(event.request);}));});

3rd step — updating the service worker

If you change or add something to the existing service worker, a new service worker will be installed. Just one service worker can be active at a time, and even a new service worker is installed, it is not active until the existing one is in use. You can try to add something in your serviceWorker.js and check the Application tab.

In order to activate the new service worker, you have to close all pages, which are controlled by the old service worker. If we want to avoid that, we can skip the waiting phase by adding self.skipWaiting() in the install event listener. The skipWaiting() method allows a service worker to activate as soon as it finishes installing. The code would look like this:

self.addEventListener(‘install’, function(event) {
// Perform install steps
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
console.log(‘Opened cache’);
return cache.addAll(urlsToCache);
})
);
self.skipWaiting();
});

4th step — manifest file

The critical element in PWAs is a web manifest file. It is a JSON format file with information about the website, such as the app’s title, paths to icons, or a background color to use in loading or splash screens.

Create a manifest.json file in the same folder where your index.html lives. My demo code looks like this:

{
“name”: “PWA demo”,
“short_name”: “Demo”,
“start_url”: “index.html”,
“icons”: [
{
“src”: “https://www.scoms.com/media/12178/jobs.png",
“sizes”: “192x192”,
“type”: “image/png”

],
“background_color”: “#3E4EB8”,
“display”: “standalone”,
“theme_color”: “#2E3AA1”
}

Let’s go through the keys and their meanings:

  • “name”: Full name of the app.
  • “short_name”: Shorter name on the home screen.
  • “start_url”: The index document to start when opening the app.
  • “icons”: The source URL, size, and type information.
  • “background_color”: The color used as the application’s default background, used during installation and on the splash screen.
  • “display”: How the app will be displayed.
  • “theme_color”: The main color for the UI used by the operating system.

When we finished defining our manifest file, let’s add in <head> of the index.html:

<link rel=”manifest” href=”manifest.json”>

5th step — generate the Lighthouse report!

In your Chrome browser’s DevTools, choose the Lighthouse tab and press Generate Report. Exciting, right?

Yes! The report detects that our app is finally a PWA!

And it’s installable! Good job!

If you go through the generated report step by step, you will see that there is a lot to be done more, but this is a great start! I would suggest to read their linked articles and make your PWA much smarter. Go crazy!

--

--