Understanding PWAs - Exploring the Twitter PWA with Dev Tools
Tags: webdev, beginners, performance, pwa
Published: 2021-04-10 23:43:53

**PWAs (Progressive Web Apps)** have been around for quite some time now. With time the PWA developer ecosystem and browser support has become mature and most of the top web platforms are now starting to add PWA support to their web apps. So what exactly is a PWA?

MDN's under construction PWA [page](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps) defines a PWA as
>"Progressive Web Apps are web apps that use emerging web browser APIs and features along with traditional progressive enhancement strategy to bring a native app-like user experience to cross-platform web applications. Progressive Web Apps are a useful design pattern, though they aren't a formalized standard."

If this definition is too vague or broad for you, you can safely assume that PWAs are web apps which run in the browser but can be "installed" on the user's smartphone or computer to provide a native app like behavior but in the browser. Generally, some offline functionality or graceful application behavior without network connectivity is expected from PWAs.

To better understand how PWAs are implemented and what better experience this web application design pattern provides, let's try to dig into and reverse engineer the Twitter PWA using the Chrome Dev Tools.

## The Manifest 📜

If your web app is going to be "installed" it needs to have some metadata, e.g the app's name, icons for different resolutions and a url to which the app opens to by default. All of this information is added in a json file present at the `/manifest.json` path.

Here is a screenshot of the Twitter's `manifest.json` file. 
![Screenshot of Twitter PWA manifest.json file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jb2cv1zguuesp4waft4z.png)
You can see the detail you can provide and the support for the possible interoperability of the Twitter Android native and the PWA app using the `android_package_name` property. Pretty powerful and feature rich!
Read more about the manifest file and what it can support [here](https://web.dev/add-manifest/).

## Service Worker 🧑‍🏭
The ❤️ of PWA - `service worker` is a JS script that lives separate from the browser page. Among other features, it provides a _network proxy_ for the web page it is running for. This means every network request originating from that page passes through the `service worker`. This opens up possibilities and provides more control over resource caching, offline application behavior and requests for resources or API calls that are sent to the server. 

![Twitter Service Worker Chrome Dev Tools Screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ppwrxdqpinwbdvzm6al3.png)

The Twitter `service worker` is registered under the `https://twitter.com/` path which means it will work as `service worker` for all paths under the `twitter.com` host. Service workers once installed against a web app keep running even when you navigate away from the page and become active every time user goes to the URL for which a `service worker` is registered in the browser. Read more about the lifecycle, features and nuances of service workers [here](https://developers.google.com/web/fundamentals/primers/service-workers).

## Cache Storage 🛍️
The `Cache Storage` [Web API](https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage) provides a simple way to implement caching of resources in the browser. It is important not to confuse this API with the default browser caching implemented by default.
![Twitter Cache Storage Chrome Dev Tools Screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/afpc9unsncwysf6mpmye.png)

As you can see there is a list of js files stored in the cache storage and each one of them has a path in the `name` field. Remember when we said that the `service worker` acts as a network proxy for the page. This means every request for these js resources originating from `twitter.com` first passes through the `service worker`. 

The `service worker` is implemented in such a way that for every resource request it first checks if the resource is present in the cache storage. If it is, the page is sent a `200 OK` response along with the required resource, without ever hitting the `twitter.com` servers. You can see a live demo of it in the Network console.
![Network Tab screenshot for twitter.com](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kruzgw2nqvtr1foed6n7.png)
As you can see in this screenshot, for the js resource `bundle.HomeTimeline...js` the request never hits the servers and the `twitter.com` page still gets the `200 OK` response along with the script.

Similarly, the HTML skeleton/shell of the Twitter app is also cached.

Even if there is no internet connection, the Twitter web app's HTML and JS will be served to the page from the `Cache Storage` by the `Service Worker`, making the app resilient to slow or no internet connectivity.

## IndexedDB 💾
Another one of the emerging web browser API that PWAs use is the [IndexedDB API](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API). The IndexedDB is an interface for storing and accessing structured data within the browser. 

Twitter makes interesting use of this feature for optimizing user experience by storing different kinds of less frequently changing metadata for the logged in user and some recent user activity so that it can be fetched directly from within the browser when needed.
![Twitter IndexedDB Chrome Devtools screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/waoztkevjc1v84y7ibdg.png)
A quick look under the `IndexedDB` category for `twitter.com` shows multiple IndexedDB instances, some with only a single Object store, some with multiple.

![Twitter IndexedDB Chrome Devtools screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f742kprnail04edj3vrn.png)

Expanding in and looking at the contents of one of the DBs with an object store called `keyvaluepairs` we can see that it has stored a list of my recently used emojis on Twitter.

![Twitter IndexedDB Chrome Devtools screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/msfsoo04rvf98zxhtjfy.png)

The Object store in the DB with the identifier `localforge` contains some more metadata about the user.

This kind of data could have been stored using good old `Local Storage` but newer features like `IndexedDB` are meant to server as an objectstore database for your application right within the browser.

## Installing the Twitter PWA ⬇️

You can use a little button in the Chrome browser URL field to install the PWA as an app.

![Twitter PWA installation Screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4ro3jge6heent87lrq4b.png)

Once installed, you now have a Twitter app icon in your dock/task bar and the app opens in a separate window different from your browser.

![Twitter PWA installed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bsk92ctpbl7yy6pkfozu.png)

## The Offline Test 🚫
Let's see what happens if I turn off my network and try opening the newly installed Twitter PWA. 

![Gif showing the behavior of Twitter PWA when offline](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wzr6o5swxr6jrzlyugdd.gif)

As you can see, the app's UI gets loaded. Most of the navigations work, but no tweets or trends data is loaded. It is **important** to understand:

- The UI works because the app's HTML and CSS are in `Cache Store` and are being served through the `service worker`
- The interactions and navigations work because the JS implementing those is also stored in `Cache Store`.
- The profile page shows some of the user metadata, which means that data is stored somewhere maybe in the IndexedDB from which the app is fetching it rather than the API.
- As the installed Twitter app is actually only a separate Chrome instance which only goes to `https://twitter.com`, but we are not seeing the 'No Internet Connection' page with a trex because the `Service Worker` is acting as a _network proxy_ and still serving content and responding to the network requests of the `twitter.com` page even without a connection to the Twitter servers.



_Phew you reached the end! Hopefully, you learned something new. If you want to ask a question, leave your thoughts about PWAs or you think there's a mistake in the article above, I'll be glad to hear from you in the comments below. You can also reach out to me on Twitter [@haseebelaahi](https://twitter.com/haseebelaahi)_ 🙂