How to install a PWA on a user's device
Tags: pwa, webdev, frontend, javascript
Published: 2019-06-23 20:29:58

Welcome to the second post about PWAs :raising_hand:

In the first article we discovered the potential of PWAs and how they differ from native apps. 
If you missed it, go and have a look at it; you might find some unknown details, even if you are already familiar with PWAs!

In this post we will see how it is possible to *install* a PWA on a user device, making it look exactly like a native app. <br> With just one touch, we can directly access our web app without interacting with the browser nor entering the web address. A much more intuitive and user friendly approach.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/f6ej9m5f1l6f7ljer8eh.gif)

<br>
&nbsp;

##Web App Manifest

MDN docs give a great and clear definition:

> The web app manifest provides information about a web application in a JSON text file, necessary for the web app to be downloaded and be presented to the user similarly to a native app (e.g., be installed on the home screen of a device, providing users with quicker access and a richer experience).

Typically, we place the web app manifest at the root of our web application. We can name it: `manifest.json` or  `manifest.webmanifest` and serve it with the media type `application/manifest+json`.

To associate a manifest to a web application, we use the `<link>` tag in the `<head>` section of an HTML document (usually index.html):

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

The snippet above indicates to the user agent that the metadata of the manifest must be adopted rather than the one in the `Document`. In case some properties are not set correctly, though, the user agent will fallback to the `Document` metadata.

The request for the manifest is made without any credentials (even if it is on the same domain). So, if the manifest requires credentials, we have to add the attribute `crossorigin="use-credentials"`:

```html
<head>
  <link rel="manifest" href="/manifest.webmanifest" crossorigin="use-credentials">
</head>
```

From MDN web docs: 
> If the attribute is not present, the resource is fetched without a CORS request (i.e. without sending the Origin HTTP header), preventing its non-tainted usage. If invalid, it is handled as if the enumerated keyword anonymous was used. 

I once had an issue in a project, where the `manifest.json` file was generating a generic error, while on localhost everything was working perfectly: 

```javascript
Manifest: Line: 1, column: 1, Unexpected token.
```

Quite a generic description :worried:

The only thing I had to do was add the `crossorigin` attribute and the manifest file was then correctly served in the browser without any errors.

Manifest files are supported by most browsers:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/o4h63ppb9x99vbdhj4ua.PNG)

Safari is currently working on adding support.

##File structure

A typical web app manifest looks like the following:

```json
{
  "short_name": "MyCoolPWA",
  "name": "My cool Progressive Web App",
  "start_url": "/?source=pwa",
  "display": "standalone",
  "icons": [
    {
      "src": "/images/icons-144.png",
      "type": "image/png",
      "sizes": "144x144"
    },    
    {
      "src": "/images/icons-192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "/images/icons-512.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "orientation": "landscape",
  "description": "A simple experiment with PWAs",
  "background_color": "#3367D6",
  "theme_color": "#3367D6"
  "scope": "/",
}
```

Let's break down the file and describe it step by step.

The following fields are mandatory to make the `add to home screen` dialog appear:

- **name/short_name:** the value used under the application icon once installed on the user's device. In Chrome, the app name is also used in the splash screen, while the PWA is loading. Short name is used if not enough space is available, therefore we should keep it short.

- **start_url:** is the path to the assets that should be loaded when the  app is launched. This is very useful as we want our application to start always from the same page (eg. home page), rather than from the last visited one in the app. 
You might wonder why we have a query string in the example above. By adding a query string to the url we allow our web analytics tools to determine how many users accessed the web app via the icon on the home screen. This gives us some more information on users' behaviour.

- **display:** Specifies how the app should be displayed in the browser. There are different values possible:

<span id="display">&nbsp;</span>
**browser:** provides a standard browser experience, exactly the same as we would access any website with a mobile device.

![browser](https://thepracticaldev.s3.amazonaws.com/i/kc7ar9kjr53l3onfpp0x.png)

**standalone:** this option is quite interesting as the application is opened in an independent window, separated from the one used by the browser, making our PWA look like it is a native app. Moreover, some UI browser elements - like the address bar - are no longer visible.

![standalone](https://thepracticaldev.s3.amazonaws.com/i/l5ciwj8n6oa5kiat6dnt.png)

**fullscreen:** as the name says, our PWA will use the whole screen of the device. No UI browser elements are rendered. This option is particularly suited for game or multimedia apps.

![fullscreen](https://thepracticaldev.s3.amazonaws.com/i/iiqbntpqbar8e0ekws11.png)


- **icons:** Indicates the icons for the browser to use when representing the app. As a minimum we have to provide an icon with at least 144px resolution.
Chrome suggests to have two: one with 192px and one with 512px resolution. Chrome will then take care to scale the icons according to the user's device. The best approach to ensure we deliver a pixel perfect experience to our users is to identify which are our target devices and then add icons with the relative resolution.

- **background_color:** sets the background color of our app. If we add the PWA to the home screen using Chrome, the background color will also be used for the splash screen.


There are also other properties, optional, but considered recommended: 
- **orientation:** allows us to specify whether the application should be displayed in portrait (vertical) or landscape (horizontal) mode. The latter is usually better for games/media apps.

- **theme_color:** on mobile devices it sets the theme color surrounding the site. On desktop, the theme color is used to style the title bar.

- **description:** describes our app.

- **scope:** defines the navigation scope of our website's context. If the user navigates outside the scope, it returns to a normal web page inside a browser window.  

If we do not want to create the manifest by hand, we can use a [manifest generator](https://app-manifest.firebaseapp.com/). This is a simple tool that provides a manifest skeleton, whereby we only have to fill out the properties with the values we want.


##Add to home screen dialog (A2HS)

To display an A2HS dialog, it is not enough to correctly initialize the manifest properties. We also need to serve the app through a secure connection (HTTPS). Chrome in particular requires the app to also have a service worker registered.
If all these points are fulfilled, the browser will show the A2HS dialog.


![a2hs](https://thepracticaldev.s3.amazonaws.com/i/afy3uqzhlb02kwd6748f.png)

If the user closes the dialog without accepting the app installation, the dialog will not appear again for around 90 days.
If the app is added to the home screen, it will look exactly like a native app, using one of the icons we defined in the manifest file. By looking at the icon, we can not tell whether there is a native app or a PWA behind it.

<figure class="image">
  <img src="https://thepracticaldev.s3.amazonaws.com/i/bm76o8n31rmy150c74uh.png" alt="a2hs-installed"><figcaption>source Mozilla web docs</figcaption>
</figure>

##Test the manifest
In order to verify that our manifest is setup correctly we can use Chrome DevTools. Open the `Application tab` and access the `Manifest section` on the left side.

![dev-manifest](https://thepracticaldev.s3.amazonaws.com/i/0o7fz1nmt2p4db6o2wd8.png)

We can see that the properties and icons defined in our manifest file are reported in this section (here the dev.to manifest file).
If you can see your manifest properties in this tab, then you are set! You correctly deployed the web app manifest to your PWA :tada:

You can also use a <a href="https://manifest-validator.appspot.com/">manifest validator</a> to validate your manifest.


In the next post (step 3) we'll discuss service workers and how we can serve our app even when the user is offline.

{% link https://dev.to/paco_ita/service-workers-and-caching-strategies-explained-step-3-m4f %}


&nbsp;
You can follow me on:
&nbsp;
<a href="https://twitter.com/paco_ita">![follow-me-twitter](https://thepracticaldev.s3.amazonaws.com/i/fgw3ppch67r8ued10oef.png)</a>
&nbsp;