What is a progressive web application?

Lemon Kazi
Oceanize Lab Geeks
Published in
4 min readSep 18, 2018

First of all, Progressive Web Applications load quickly. Now, we will be able to do this by creating what is known as an app shell, a very small part of the application that loads quickly and then loads other data as needed. When developing your Progressive Web Application you should plan for it to be responsive so that you can use the same applications in as many devices in whatever orientation you need.

Progressive Web Applications should be designed to work offline. You can do this by using the technology called service workers, which will cache your application assets. The next time the application loads, it will load from the cache and it will do so a lot quicker, even if the internet is not currently working. By using a special file called the Manifest, your application will be easy to install in mobile devices as well as regular desktops.

These are the five features that make a web app progressive. So, let’s take a look at what we are going to build.

For help you can follow steps from here

https://codelabs.developers.google.com/codelabs/your-first-pwapp/#1

Download the Code

Click the following link to download all the code for this exercise:

Install and verify web server

While you’re free to use your own web server, this codelab is designed to work well with the Chrome Web Server. If you don’t have that app installed yet, you can install it from the Chrome Web Store.

Otherwise you can use NPM for setting webserver

Let’s go ahead and clear this out in our terminal and now we’ll issue an npm install command to install all the modules for this project. You may need to run sudo npm install depending on how your permissions are set. Once the npm installation is done, we can clear this out, and then you should be able to run the command.

http-server ./ -p 8787

Now let’s get started building this application.

The application uses a technology called Service Workers to make sure that our application can work offline by caching all of the assets into a special location within the browser.

First, we need to check if the browser supports service workers, and if it does, register the service worker. Add the following code to app.js

if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('./service-worker.js')
.then(function() { console.log('Service Worker Registered'); });
}

Cache the site assets

When the service worker is registered, an install event is triggered the first time the user visits the page. In this event handler, we will cache all the assets that are needed for the application.

Add this code to your new service-worker.js file:

var cacheName = 'weatherPWA-step-6-1';
var filesToCache = [
'/',
'/index.html',
'/scripts/app.js',
'/styles/inline.css',
'/images/clear.png',
'/images/cloudy-scattered-showers.png',
'/images/cloudy.png',
'/images/fog.png',
'/images/ic_add_white_24px.svg',
'/images/ic_refresh_white_24px.svg',
'/images/partly-cloudy.png',
'/images/rain.png',
'/images/scattered-showers.png',
'/images/sleet.png',
'/images/snow.png',
'/images/thunderstorm.png',
'/images/wind.png'
];
self.addEventListener('install', function(e) {
console.log('[ServiceWorker] Install');
e.waitUntil(
caches.open(cacheName).then(function(cache) {
console.log('[ServiceWorker] Caching app shell');
return cache.addAll(filesToCache);
})
);
});

First, we need to open the cache with caches.open() and provide a cache name. Providing a cache name allows us to version files, or separate data from the app shell so that we can easily update one but not affect the other.

Finally, update the fetch event handler to handle requests to the data API separately from other requests.

self.addEventListener('fetch', function(e) {
console.log('[Service Worker] Fetch', e.request.url);
var dataUrl = 'https://query.yahooapis.com/v1/public/yql';
if (e.request.url.indexOf(dataUrl) > -1) {
/*
* When the request URL contains dataUrl, the app is asking for fresh
* weather data. In this case, the service worker always goes to the
* network and then caches the response. This is called the "Cache then
* network" strategy:
* https://jakearchibald.com/2014/offline-cookbook/#cache-then-network
*/

e.respondWith(
caches.open(dataCacheName).then(function(cache) {
return fetch(e.request).then(function(response){
cache.put(e.request.url, response.clone());
return response;
});
})
);
} else {
/*
* The app is asking for app shell files. In this scenario the app uses the
* "Cache, falling back to the network" offline strategy:
* https://jakearchibald.com/2014/offline-cookbook/#cache-falling-back-to-network
*/

e.respondWith(
caches.match(e.request).then(function(response) {
return response || fetch(e.request);
})
);
}
});

Beware of the edge cases

As previously mentioned, this code must not be used in production because of the many unhandled edge cases.

Cache depends on updating the cache key for every change

For example this caching method requires you to update the cache key every time content is changed, otherwise, the cache will not be updated, and the old content will be served. So be sure to change the cache key with every change as you’re working on your project!

Requires everything to be redownloaded for every change

Another downside is that the entire cache is invalidated and needs to be re-downloaded every time a file changes. That means fixing a simple single character spelling mistake will invalidate the cache and require everything to be downloaded again. Not exactly efficient.

Browser cache may prevent the service worker cache from updating

There’s another important caveat here. It’s crucial that the HTTPS request made during the install handler goes directly to the network and doesn’t return a response from the browser’s cache. Otherwise the browser may return the old, cached version, resulting in the service worker cache never actually updating!

Beware of cache-first strategies in production

Our app uses a cache-first strategy, which results in a copy of any cached content being returned without consulting the network. While a cache-first strategy is easy to implement, it can cause challenges in the future. Once the copy of the host page and service worker registration is cached, it can be extremely difficult to change the configuration of the service worker (since the configuration depends on where it was defined), and you could find yourself deploying sites that are extremely difficult to update!

--

--