Supercharge Your Website Using PWA: Installable Website
Tags: pwa, webdev, ux, javascript
Published: 2021-04-18 04:51:53

# What is a `PWA`?

**Progressive Web Apps** (`PWA`) are **web applications** that have been designed so they are **capable** (utilize native features), **reliable** (work even in offline mode), and **installable**. These three pillars transform them into an experience that feels like a platform-specific application.

# Why use `PWA`?

At their heart, **Progressive Web Apps** are just web applications. Using progressive enhancement, new capabilities are enabled in modern browsers. Using `service workers` and a `web app manifest`, a web application can be converted into a `PWA`. If the new capabilities aren't available, users still get the core experience.

![Comparison between native app, web app and pwa](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wg6fsytyd1lbzhp55ys9.PNG)

As it can be seen from the picture above, `PWA` offers the best of both worlds by delivering a web experience your users will love, using the latest web features to bring enhanced **capabilities** and **reliability**, **Progressive Web Apps** allow what you build to be installed by anyone, anywhere, on any device with a **single codebase**.

# Getting Started

The requirements for a website to be turned into a `PWA` are:
- The website itself (served over `https` or from `localhost`)
- `manifest.json` (provides information about a **web application**)
- `service worker` (a **script** that allows **intercepting** and **control** of how a **web browser** handles its `network requests` and `asset caching`.)

Here we will not be focusing on creating a website, but on making an existing website installable. To follow along just use a basic website like the one given below.

```html
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>PWA: Installable website</title>
	</head>
	<body>
		<h1>Test</h1>
	</body>
</html>
```

**NOTE:** Its possible to style the site or add scripts, but for the purpose of adding `PWA` installation feature, this will suffice.

The defination of `manifest.json`

```json
{
  "name": "<name of the application>",
  "short_name": "<short name for the application> (can be same as name)",
  "start_url": "<start url for the website>",
  "display": "<display mode for the website>",
  "description": "<description of the application>",
  "background_color": "<color>",
  "theme_color": "<color>",
  "orientation": "<orientation>",
  "icons": [{
    "src": "<image source>",
    "sizes": "<widthxheight>",
    "type": "image/png"
  }]
}
```

An example `manifest.json` would look like 

```json
{
    "name": "PWA: Installable website",
    "short_name": "Installable PWA",
    "start_url": "index.html",
    "display": "standalone",
    "description": "App for testing PWA features",
    "background_color": "#ffffff",
    "theme_color": "#000000",
    "orientation": "portrait-primary",
    "icons": [
        {
            "src": "image/icon-24.png",
            "sizes": "24x24",
            "type": "image/png"
        },
        {
            "src": "image/icon-32.png",
            "sizes": "32x32",
            "type": "image/png"
        },
        {
            "src": "image/icon-48.png",
            "sizes": "48x48",
            "type": "image/png"
        },
        {
            "src": "image/icon-64.png",
            "sizes": "64x64",
            "type": "image/png"
        },
        {
            "src": "image/icon-128.png",
            "sizes": "128x128",
            "type": "image/png"
        },
        {
            "src": "image/icon-256.png",
            "sizes": "256x256",
            "type": "image/png"
        }
    ]
}
```

To add the manifest to the website, add the following in the `head` section

```html
<link rel="manifest" href="manifest.json" />
```

Its a good practice to add the following in the `head` section as well for **iOS** support

```html
<link rel="apple-touch-icon" href="image/icon-24.png" />
<link rel="apple-touch-icon" href="image/icon-32.png" />
<link rel="apple-touch-icon" href="image/icon-48.png" />
<link rel="apple-touch-icon" href="image/icon-64.png" />
<link rel="apple-touch-icon" href="image/icon-72.png" />
<link rel="apple-touch-icon" href="image/icon-96.png" />
<link rel="apple-touch-icon" href="image/icon-128.png" />
<link rel="apple-touch-icon" href="image/icon-256.png" />
<meta name="apple-mobile-web-app-status-bar" content="#db4938" />
<meta name="theme-color" content="#db4938" />
```

Now only the `service worker` is left to be dealt with.

`service-worker.js`

```javascript
const STATIC_CACHE = "static-cache-v1"
const static_assets = [
    "/",
    "/index.html",
    "/script.js",
    "/image/icon-24.png",
    "/image/icon-32.png",
    "/image/icon-48.png",
    "/image/icon-64.png",
    "/image/icon-72.png",
    "/image/icon-96.png",
    "/image/icon-128.png",
    "/image/icon-256.png",
]

// storing static assets in cache on service worker install
self.addEventListener("install", event => {
    event.waitUntil(
        caches.open(STATIC_CACHE).then(cache => {
            cache.addAll(static_assets)
        })
    )
})

// returning static assets from cache
self.addEventListener("fetch", event => {
    event.respondWith(
        caches.match(event.request).then(response => {
            return response || fetch(event.request);
        })
    )
});
```

We are required to handle the `fetch` event to enable installation.

Enable the `service worker` by adding the following script in the website

```html
<script>
    if ('serviceWorker' in navigator) {
        navigator.serviceWorker.register('/service-worker.js');
    } else {
        console.log("Service worker is not supported");
    }
</script>
```

Now the last piece of the puzzle, serving the website on `localhost`. If you are using **VS Code**, you can easily do it using the [live server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) extension (recommended for beginners).

![Installable website](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w7ihpyv0law1di89773h.png)

The installation icon on the top right of the url-bar signifies its now installable. Click it to install the `pwa` on your device.

**NOTE**: This is just a brief overview. In a production grade `pwa` its more advisible to periodically refresh the **static assets** as well to ensure that the user don't access outdated content.

# Project using this Implementation

**Smartsapp**

Web-app: [https://smartsapp-ba40f.firebaseapp.com](https://smartsapp-ba40f.firebaseapp.com/)

{% github https://github.com/ruppysuppy/SmartsApp %}

# Reference

1. [web.dev/what-are-pwas](https://web.dev/what-are-pwas/)
2. [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps)

Finding **personal finance** too intimidating? Checkout my **Instagram** to become a [**Dollar Ninja**](https://www.instagram.com/the.dollar.ninja/)

# Thanks for reading

Reach out to me on:

-   [GitHub](https://github.com/ruppysuppy)
-   [LinkedIn](https://www.linkedin.com/in/tapajyoti-bose-429a601a0)
-   [Portfolio](https://tapajyoti-bose.vercel.app) (For freelance projects, reach out through the contact form)