How To Get Your Site To Be Downloaded As PWA As Fast And Easy As Possible (quick-start)

Liam Zety
6 min readJan 17, 2021
Photo by Daniel Korpai on Unsplash

In this tutorial i will guide you on how to turn your application into a PWA with two easy steps.

Please make sure to follow all steps otherwise this feature will not work.

Do note that this is a quick start, for a more personalized and specific configuration refer to the sources below.

But first, what is PWA?

A progressive web application (PWA) is a type of application software delivered through the web, built using common web technologies including HTML, CSS and JavaScript. It is intended to work on any platform that uses a standards-compliant browser, including both desktop and mobile devices.

While web applications have been available for mobile devices from the start, they have generally been slower, have had fewer features, and have been less used than native apps. PWA features narrow the gap between user experience in web-based and native applications. Features include

  • Ability to run offline
  • High performance
  • Background processing in service workers in a separate thread
  • Access to the phone’s sensors
  • Support for push notifications
  • An icon on the phone‘s home screen
  • Ability to run on desktop

In short, PWA makes your app run on mobile / desktop just like a native mobile / desktop app — with added benefits.

https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps

https://en.wikipedia.org/wiki/Progressive_web_application

Step 1 — Manifest

Provide a manifest.json file, put it in the public folder (same path as index.html).

Provide it with logos (make sure the logos are in the right size and are places in the public folder.)

{
"name": "AppName",
"short_name": "AppName",
"start_url": ".",
"display": "standalone",
"background_color": "#fff",
"description": "App Description",
"icons": [
{
"src": "logo48.png",
"sizes": "48x48",
"type": "image/png"
},
{
"src": "logo144.png",
"sizes": "144x144",
"type": "image/png"
}
]
}

Link it at index.html

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

In short, the manifest will tell the browser data about your application, there are more options available but these are generally what you will need. for more detailed explanation about manifest.json check here —

https://web.dev/add-manifest/

Step 2 — Service Worker

What is a service worker?

A service worker is a type of web worker. It’s essentially a JavaScript file that runs separately from the main browser thread, intercepting network requests, caching or retrieving resources from the cache, and delivering push messages.

Since workers run separately from the main thread, service workers are independent of the application they are associated with. This has several consequences:

  • Because the service worker is not blocking (it’s designed to be fully asynchronous) synchronous XHR and localStorage cannot be used in a service worker.
  • The service worker can receive push messages from a server when the app is not active. This lets your app show push notifications to the user, even when it is not open in the browser.

Create a serviceWorker.js file, make sure to it in the public folder (same path as index.html).

/* servieWorker.js */console.log('Service Worker Registered!');self.addEventListener('install', event => {    console.log('Installing service worker...');    const urlsToCache = [
'/',
];
event.waitUntil(
caches.open('my-cache1').then(cache => {
return cache.addAll(urlsToCache)
})
);
});
self.addEventListener('fetch', event => { event.respondWith(
// the response is resolved to null if there is no match
caches.match(event.request)
.then(response => {
let res = response;
if (!res) {
res = fetch(event.request)
}
return res
})
);
})

In your main javascript file connect sw.js with a relative route

/* main.js */
navigator.serviceWorker.register('./serviceWorker.js');

This file (main.js) can be placed anywhere if you’re using webpack but the path stated above stays the same so you dont have to worry about it.

https://developers.google.com/web/ilt/pwa/introduction-to-service-worker

Final result in browser:

Browser identifies manifest.json
Browser identifies the Service Worker
Browser adds an install button to the urlbar

If you get the same results as the images above then that means that your Manifest and Service Worker are both registered and working as intended, and by all means WE ARE DONE!

Step 3 (BONUS) — Add popup and install button

In this step i’ll show you how to create a popup with an install button that detects if the user has already installed your app (if so, the popup will not appear!) for a much, much better user experience.

This is the popup to show if the app is not installed with a button to install (with styles).

<main>   <h1>Service Worker Demo</h1></main><div class="install-popup">  <div class="container-popup">   <div class="word-container">     <h2>Install our awesome app!</h2>     <p>No download required. Click install to add the app to                your home screen.</p>   </div>     <button class="install-btn">       + INSTALL     </button><button class="close-btn">  X</button>  </div></div><!-- Styles for the popup, can be places in your styles.css file --><style>* {  box-sizing: border-box;  font-family: sans-serif;}body {  margin: 0;}main {  margin-top: 100px;}button {cursor: pointer;}.install-popup {  display: none;  position: fixed;  line-height: 1.5;  top: 0;  left: 0;  width: 100%;  background-color: rgb(226, 60, 143);  box-shadow: 0 10px 10px rgba(0, 0, 0, 0.137);  padding: 10px 20vw;  color: #f1f1f1;}.install-popup * {  margin: 0;}.container-popup {  display: flex;  align-items: center;  justify-content: space-between;  flex-wrap: wrap;  margin-bottom: -25px;}.word-container {  margin-bottom: 25px;}.install-btn {  display: flex;  align-items: center;  cursor: pointer;  font-size: 1em;  height: 40px;  padding: 0 15px;  color: #f1f1f1;  background-color: rgb(226, 60, 143);  box-shadow: 5px 5px 10px rgb(204, 64, 134),  -5px -5px 10px rgb(227, 84, 156);  border: none;  border-radius: 35px;  font-weight: 700;  margin-bottom: 25px;}.close-btn {  position: absolute;  top: 5px;  right: 5px;  background: none;  border: none;  color: #f5f5f59f;  font-size: 1.5em;}@media (max-width: 1080px) {.install-popup {  top: auto;  bottom: 0; }}</style>

Copy and paste the following into main.js

console.log('App starting up!... ');// variable store eventwindow.deferredPrompt = {};const installPopup = document.querySelector(".install-popup");const installBtn = document.querySelector(".install-btn");const closeBtn = document.querySelector(".close-btn");window.addEventListener("beforeinstallprompt", (e) => {// this event does not fire if the application is already installed  installPopup.style.display = "block";  e.preventDefault();// store install avaliable event  window.deferredPrompt = e;// wait for click install button by user  installBtn.addEventListener("click", () => {   window.deferredPrompt.prompt();   window.deferredPrompt.userChoice.then((choiceResult) => {    if (choiceResult.outcome === "accepted") {    // user accept the prompt    // we hide the popup    installPopup.style.display = "none";   } else {    console.log("User dismissed the prompt");    }    window.deferredPrompt = null;    });  });   closeBtn.addEventListener("click", () => {    installPopup.style.display = "none";   });});// if standalone android OR safariif (window.matchMedia("(display-mode: standalone)").matches ||window.navigator.standalone === true) {  // hide the popup  installPopup.style.display = "none";}// do action when finished the installwindow.addEventListener("appinstalled", () => {  console.log("success app install!");});const handleInstall = () => {  window.deferredPrompt.prompt();  window.deferredPrompt.userChoice.then((choiceResult) => {   if (choiceResult.outcome === "accepted") {    // user accept the prompt    // we hide the popup    setIsAppInstalled(false)   } else {    console.log("User dismissed the prompt");   }   window.deferredPrompt = null; });}navigator.serviceWorker.register('./serviceWorker.js');

That’s it! you now have a working PWA application that runs like a native app on both desktop and mobile! complete with an install button and a popup.

Sources:

--

--

Liam Zety
0 Followers

Full-Stack / Frontend Web Developer