How to Create Progressive Web Application using Service Worker in JavaScript….

Yudhajit Adhikary
16 min readMar 20, 2020

Hi, This is a introductory article of Progressive Web Application .In this article we will go through the basic concepts of PWA which are as follows:

  1. What is Progressive Web Application ?
  2. Why we need Progressive Web Application ?
  3. What is difference between Native Application and Progressive Web Application ?
  4. What are the technical components of Progressive Web Application ?
  5. Discussing how to create PWA along with whole code walk through
  6. Observations
  7. Conclusion
  8. What is Progressive Web Application ?

In the last few years there was been exponential growth in the number of mobile phone users. Today more than 60% of total internet usage is happening via mobile phone.Obviously ,the reason include portability, cheap hardware, easy access to the internet or increased number of service on the internet,with more users on mobile, the optimization of user experience on the phone is essential.

If companies have a dedicated native web application,there is a possibility that many users will prefer there web version to avoid downloading and installing to handle a memory constraint for any other personal preference.This type of native web applications are known as Progressive Web Application.

2. Why we need Progressive Web Application ?

  1. Reliable :

The application should be lightning fast when loading ,it should be close to instantaneous , should also open when there is no internet or fairly low speed internet like 2G , Google found that 53% of the user abandon the website if the page took longer than 3 second to load.

2. Fast :

The scrolling of page should be smooth, when the user is interacting with the web application.

3. Responsive:

The application should fit in all the different size of devices .

4. Installable:

If we want to make web application closer to native application, they have to be install or should reside in the home screen.

5. SplashScreen :

Progressive Web Application adds a splash screen during the startup of the application,this make the PWA feel more like a native application.

3. What is difference between Native Application and Progressive Web Application ?

Let’s start with Native Application features:

  1. Made with framework or device specific SDK’s.
  2. Published & then downloaded from the app store.
  3. Can be installed on the mobile home screen.
  4. Runs on the device itself with access to device features.
  5. Can be used offline.
  6. Can use application push notification.

Now let’s see the Progressive Web Application features:

  1. Can be made with vanilla JavaScript , CSS and HTML.
  2. Accessible via a web address but not from the application store.
  3. Can be installed on the mobile home screen.
  4. Runs in the browser but with access to device features.
  5. Can be used offline.
  6. Can use web push notifications.

4. What are the technical components of Progressive Web Application ?

PWA has some important technical components which work together and energizes the regular web app. The following components are required to develop a good PWA.

  1. Service Worker.
  2. Manifest.json.
  3. HTTPS.

Let’s discuss each one of those briefly.

  1. Service Worker:

A Service worker is just a component of JavaScript code which works as a proxy between the browser and the network. A Service worker manages the push notifications and helps to build the offline first web application using the browser’s cache API.Let’s discuss this more technically.

Service Worker Concepts

When we create a website that might be a combination of HTML ,CSS and JavaScript files . The JavaScript file (App.js) runs on a single thread inside the browser and is tightly coupled with the HTML Page , it can access the DOM and manipulate the DOM content,thus connection between JavaScript ,CSS and HTML file is bind strongly. Now when we create a ServiceWorker.js it does not run on the same thread as our regular JavaScript.It runs on a different thread on another path, Isolated alone from HTML Page because of that it does not access the DOM. ServiceWorker.js is the background processor, They work to handle the application functionality like on listening and reacting to the events which is happening in browser such as Push Notification made in server, fetch HTTP made by browser etc .So Service Worker run in a background listening for the different events and it can react on it, do something when event occurs, now what exactly they do to know this we have to know another concept of Service Worker which is Service Worker Life cycle. Let’s discuss that now:

Service Worker Life Cycle:

When we create a service worker it goes through a custom Life Cycle ,this is really important concept to grasp:

Initializing Service Worker

So initializing of Service Worker begins from App.js which is the root JavaScript file , It actually register service Worker with browser. We actually create a JavaScript file (sw.js) which acts as the service Worker ,we will discuss about it when we will start coding .Thus in App.js we actually tell the browser that sw.js should be registered as serviceWorker and put it on the separate serviceWorker thread. When browser fire the install event browser basically is installing the service Worker , When this service Worker gets installed browser fires an active event ,once serviceWorker is active,it can access all the different pages , all the different files inside it’s scope.One important thing is that we have to create the sw.js file on the root directory because serviceWorker have it’s scope only on that directory in which it is present.

Service Worker when Page is Reload

If we reload the page the service worker goes through exactly the same lifecycle ,when we refresh the page service worker is still registered because that happens inside app.js. But in change it will reinstall it or it stop a server and remain in waiting to be activated meanwhile the old service worker is gonna continue to be activated by default.

Service Worker on closing all tabs and then re -open

A new service Worker is only gonna activate if all the instance of the our application is closed.

2. Manifest.json:

The manifest file is a config JSON file which contains the information of your application, like the icon to be displayed on the home screen when installed, the short name of the application, background color, or theme.

If the manifest file is present, the Chrome browser will automatically trigger the web app install banner, and if the user agrees, this adds the icon to the home screen and the PWA is installed.We will discuss about it later when we will be creating our Progressive Web Application.

3. HTTPS:

Service workers have the ability to intercept the network requests and can modify the responses. Service workers perform all the actions on the client side. Hence, PWA requires secure protocol HTTPS.

The service worker has the ability to receive push notifications and background sync, which definitely increases the user experience and keeps the customer engaged. Push notification and background sync are optional, but are recommended to provide a more native-like experience.

4. Discussing how to create PWA along with whole code walk through

Now it’s enough theoretical stuffs done let’s start coding..

So the application which we are going to build is a food restaurant application where we can add food in our menu ,it also having contact us page and about page of the restaurant. We will build that application, we will apply PWA on it ,we will implement add to home screen ,will run the application offline and will also run audit test on our application.

So first let’s see the folder structure of our code base:

Folder Structure

We have created css folder we have build our application using materialize css which will provide materialize.min.css file and materialize.min.js file we will keep the css file inside css folder,and inside css it’s having styles.css file which is having the styling part of our application.Then we have image folder having our application logo or icon . Js folder is having app.js the root javascript file, db.js maintains the backend of our application , ui.js maintains the frontend part of our application.The pages folder is having all the pages like about page ,contact us page and fallback page. Index.html is the root html . manifest.json is the manifest file which will contain all the information of your application, like the icon to be displayed on the home screen when installed, the short name of the application, background color, or theme.And lastly sw.js is the service worker of our application. Now let’s see the App.js :

App.js

In App.js we are checking whether there is service worker in navigator, navigator is javascript object that represents the browser information about it,as we can see we are looking if there is service worker on navigator object and if there is service worker ,we are registering sw.js as the service worker of the browser and it will be a promise if it get’s successfully registered it will console.log success message otherwise it will console.log error message. Now let’s see the index.html:

index.html
index.html
index.html
index.html

In Index.html we have added a title ,added several link for material icon , style.css , material.min.js , manifest.json. For materialize css visit the website click on get started ,cdn are available there ,and download the folder under materialize ,that folder will have the materialize.min.js and materialize.min.css file copy those and paste it into your codebase. After that we create our top navigation then we create our side nav that opens when we click on the menu icon of our top navigator which is having several options like Home, About and Contact . After that we have designed our body part having plus button if we click on it ,it opens a form having two fields Recipe Title and Ingredients on submitting the form the recipe gets added to our food menu list . After that our code is having cdn that we have to get from firebase firestore to store the data for our backend to get the cdn we have to go to firestore website, then we have to login ,create a project,after creating project screen like this will appear:

Firebase Dashboard having Project name

After clicking on the project your project dashboard will appear :

Firebase Project Dashboard

After that in order to store the data we have to create a database for that click on Cloud Firestore and create a database on test category or mode after that a screen like this will appear:

Firebase Firestore database

After that click on start collection button :

Creating collection and adding fields in Firebase FireStore

In my case I have created a recipes collection having two fields title having type string and value soup and ingredients having type string and value tomato, After that click on Save button.

Thus we have created the database that will store our data and in order to use this firestore in our application we have to added the cdn provide by firestore in our codebase. For that cdn click on home button ,after that click to setting icon then we will see a screen like this:

Firebase Details

Now if we scroll down ,we will see a cdn tab click on it we will get a code copy it and will place that inside our code base ,we have to modify little bit in that code after the firebase link :

<script src=”https://www.gstatic.com/firebasejs/7.11.0/firebase-firestore.js"></script>

and add this line before the script tag ends:

const db = firebase.firestore();

Thus our backend is ready and firestore is connected with our application.Now let’s see the manifest file(manifest.json):

manifest.json

In manifest.json we have created an object having all the information about the application thus name : ‘Gweta FoodCorner’ it’s the name of the application, short_name means the name that will appear below the icon of the application ,start_url means the first page which will be displayed,display : ‘standalone’ means the application will not show the address bar which will make it look like a native app, background_color and theme_color determines the background color and theme color of the splash screen of our application, orientation : ‘portrait-primary’ means our application will open in a portrait mode, icons is a array of object having the several properties of icon of our application.Now let’s see our service worker file which is sw.js:

sw.js
sw.js
sw.js

In sw.js we define the whole workflow of our service worker.The service worker used to store all the html ,javascript and css file into cache so that it can render those even if it’s running offline. So there are two type of cache which we want to create one is static and another is dynamic. Static cache will store all the basic thing which are required for a static page that is index.html and dynamic cache will store all the file related to the our pages like about page ,contact us page etc. Actually sw.js acts as a proxy when our application make a request it go through sw.js , sw.js can listen and react to the fetch request , eventually our sw.js will usually cache all assets. So how this caching actually happens the first thing which happens in service worker lifecycle is the browser first install the service worker so the browser first trigger install event . ‘/’ is the request Url it takes all the request Url make that request and then return back the assets from that request.This caching might take some time.So browser may stop and let service worker to complete it after that caching is done. After that when caching is done and service worker is installed then it get activate phase there we perform version caching.When there is some change in the Dom we will change the version value of our cache like now we have staticCacheName= ‘site-static-v’ after changing in Dom we will make it ‘site-static-v1’ if we now change something in our DOM the changes will not reflect in our application this is because the service worker is using the old version of the cache storage thus when there is some change in the DOM we want the service to delete the older version of the cache this is called version caching. Thus we are looking for the keys array having all the cache our service worker is using so we are filtering those cache version which is not equal to our current cache version and deleting those , thus after doing this we will see the DOM changes will appear in our Application.Now comes the important part of service worker which is fetch function so how actually service worker manage the offline rendering of the website. So fetch event have a request.url which looks whether the fetch request is coming from (firestore.googleapis.com ) firestore if it is not then service worker will respond the event with the cache storage value , it will match the cache with the event request if it matches it will return the assets present in the cache ,else it will allow the normal fetch event from the backend .Now we have discussed earlier that there are another cache which is a dynamic cache named dynamicCacheName so how this dynamic cache is build the service worker perform a fetch operation on the event request and whatever response it gets it put them into the dynamic cache as key value pair where event.request.url is the key and fetch response as the value. limitCacheSize is a cache size limiting function which takes two parameter cache name and size it checks the all the keys means cache length and if it is greater than the size passed it simple deletes the excessive assets from the cache. After cache size limiting we are returning the fetch response.If some errors occurs means the html file which is requested is not present in cache then we will display our fallback page from our cache . Now let’s see db.js file:

db.js

In db.js we are actually doing three things persisting out data so that offline data is enabled ,creating real time listener means if our application is offline the ui will be updated according to the changes made from frontend but the database modification in firestore or backend will happen when the application will be online, and another thing is adding new recipe in our menu list.db.enablePersistence actually helps in persisting our data for offline mode .Whenever some changes occurs in the database from frontend even if the application is offline it reflect those changes in Ui using onSnapshot method ,this onSnapshot returns a object ,this object has method docChanges () which has all properties of the changes happened from frontend to the database, we check if that change type is added we are calling a render method (renderRecipe)where we are sending the changed data and changed document id, renderRecipe is defined in ui.js. Actually service worker used IndexedDb for storing the data offline ,when the application is offline all the changed gets reflected in the indexedDb and when the application runs online the changes gets reflected in the actual backend.

IndexedDB Concept

Last thing in db.js is adding new recipe we are having a form having class name ‘form’ we are getting value from that form title and form ingredients fields and storing it on recipe object in a key value pair and finally add recipe to the recipes collection .Now lets see the ui.js file:

ui.js

Ui.js is having mainly materialize syntax which we are not going to discuss much. we have defined renderRecipe here we are taking added recipe title and ingredients and rendering in the frontend and finally appending it inside the div having ‘recipes’ as class Name.Last thing which is remaining now is the pages folder those are self explainetory we can just go through them,those are just normal html:

about.js
about.js
contact.js
contact.js
fallback.js
fallback.js

So our Progressive Web Application is now ready.

6. Observations:

Let’s run the live server and see the output:

Output when it is online

If we open the google develop tool and check the console we will see two console.log first caching shell assets and service worker registered.

Console log on first rendering

Let’s see our About page :

About Page

Let’s see our contact us page:

Contact Us Page

Let’s see our side navigation bar:

Side Navigation bar

We can also add menu on list on clicking on the add button:

Adding New Recipe in our Menu List

Now if we go to application in google developer tool inside service worker we will see status of the server worker is running:

Service Worker of our Application

If we now check the Manifest file we will see all the details we have added to our manifest file include the icon available there:

Manifest file of our Application

Now let test the application offline if we check the offline checkbox and refresh our website still renders.

Our Application in Offline Mode

Let’s check the about page offline:

Our About Page in Offline Mode

Let’s check the contact us page offline:

Our Contact Us page in Offline Mode

Let’s try to add new recipes offline:

Adding New Recipes in Offline Mode

Let’s now run audit test for running test we have to go audit tab in google developer tool run test and here is our PWA Report :

Audit test Report

Now let’s see what is cached in our static Cache by our service worker in our application:

Static Cache Storage

Now let’s see what is cached in our dynamic Cache by our service worker in our application:

Dynamic Cache Storage

Now there is only one thing remaining to observe that is Add to Home Screen .If your application is running you will see a add button on the right of your address bar , you just click it and add your web application in your homework. Now to test whether the application is added to the home screen or not , if we share our application on windows search engine :

Our Application added to Home Screen

Hurry! We got our Gweta Food Corner application into our system , this is really cool .

7. Conclusion:

Ohh! It’s really a long article .There are many other ways of building Progressive Web Application, I think this article will be helpful to whom who wants to get some kick start on building Progressive Web Application .I am leaving my github link down below for the code base of the application.

One last thing I want to say to everyone that stay safe, stay at home .We can win the fight against Corona Virus together , always be thankful to the peoples out there fighting for us for our safety, the doctors,the nurses, airport staffs, municipal cleaning staffs everyone .And lastly we should never forget the very root of our existence which is our Nature,our Mother Earth .

HAPPY CODING :)

--

--

Yudhajit Adhikary

Web developer by profession,Photographer,Blog Writer,Singer,Pianist,Seeker of Solution