ブラウザショートカットとしてのA2HS

[mediba Advent Calendar 2021](https://qiita.com/advent-calendar/2021/mediba)の5日目です。

「WebサイトへのショートカットをOSのホーム画面へ追加可能する」施策を検討しておりまして、私自身がホーム画面追加(Add to home screen/A2HS)における実装方法やブラウザ挙動についてよく理解していなかったため、いくつかのブラウザで検証してみました。
## ホーム画面追加とは

PWAにおけるホーム画面追加は「Webアプリ扱いでのインストール」と「ブラウザショートカット追加」の2つのモードがありますが、今回はあくまでブラウザ利用の延長として考えていたため、この記事では後者の実装について触れています。

ブラウザが対応していれば、メニューから操作することでmanifest.jsonで指定された固定のURL・タイトル文字・画像URLでホーム画面へのショートカット追加が可能となります。

### メニューとしての表示

今回は「ホーム画面に追加」と表示されていますが、一定の条件を満たすとアプリ扱いになり「アプリをインストール」と表示されます。

![cap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/d56381ab-4c95-87ee-2f38-8ff5c0498a9b.png)

### ホーム画面追加後の表示

manifest.jsonで指定した任意のタイトル文字、遷移先URL、画像が設定され、Androidであれば対応するブラウザのロゴも重なって表示されます。

![Screenshot_20211204-211755_One UI Home.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/2aee6ecf-5511-d062-f2d0-428f02642b2d.jpeg)

icons配列の各オブジェクトで`"purpose": "maskable"`と指定することで、上記画像の左側のようにマスクを掛けることもできます。
https://web.dev/maskable-icon/

ホーム画面に追加するだけの場合にPWAと言っていいのかわかりませんが、ブラウザはWeb App Manifestを解釈しているようですので、いったんPWAとしておきます。

## manifest.jsonの有無による挙動の違い

さて、manifest.jsonで`"display":"browser"`としてiOS Safari、Chrome for Android v96、Firefox for Android v94で検証してみたところ、以下のような挙動となりました。 

### タイトル文字の参照

iOS Safariはapple-mobile-web-app-titleに対応していますが、manifest.jsonにshort_name指定があればそちらが優先されます。

|               | manifest.jsonが無い場合                | manifest.jsonで指定した場合           |
|----------------|----------------------------------------|---------------------------------|
| iOS Safari            | metaタグのapple-mobile-web-app-title | manifest.jsonのshort_name |
| Chrome for Android | titleタグ                | manifest.jsonのshort_name |
| Firefox for Android |      titleタグ            | titleタグ ※ |

### 遷移先URLの参照

iOS SafariとChrome for Androidは同じ挙動となりました。
manifest.jsonでstart_urlを指定することでURLを固定させることができます。

|                |manifest.jsonが無い場合     | manifest.jsonで指定した場合         |
|----------------|-------------------------|---------------------------------|
| iOS Safari            | ホーム画面追加時のlocation.href   | manifest.jsonのstart_url  |
| Chrome for Android | ホーム画面追加時のlocation.href  | manifest.jsonのstart_url |
| Firefox for Android |      ホーム画面追加時のlocation.href   |ホーム画面追加時のlocation.href ※ |

### アイコン画像URLの参照

iOS Safariの場合はmanifest.jsonのiconsが反映されず、apple-touch-icon-precomposedで指定された画像が固定で読み込まれるようでした。

|                | manifest.jsonが無い場合                     | manifest.jsonで指定した場合                  |
|----------------|------------------------------------------|------------------------------------------|
| iOS Safari            | linkタグのapple-touch-icon-precomposed | linkタグのapple-touch-icon-precomposed |
| Chrome for Android | linkタグのapple-touch-icon-precomposed | manifest.jsonのicons配列               |
| Firefox for Android |       linkタグのapple-touch-icon-precomposed          | linkタグのapple-touch-icon-precomposed ※ |

※Firefoxではdisplayがbrowserの場合にはmanifest.jsonの内容が反映されません。
※ブラウザショートカットに限定すればServiceWorkerは不要となります。


## というわけで

ブラウザショートカットとしてのA2HSを設定するには最低限以下の内容で実装すれば良さそうです。

### ・manifest.jsonを設定

アイコン画像URL、遷移先URL、タイトル文字列、表示モード(display)、アイコンのマスクの有無を指定します。

今回は`"display":"browser"`としていますが、前述したようにFirefoxはbrowserの場合にmanifest.jsonを参照しないため、Firefoxも含める場合にはminimal-ui等を検討してもいいかもしれません。


```JSON
{
  "icons": [
    {
      "src": "/img/icon_192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "maskable"
    },
    {
      "src": "/img/icon_512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "maskable"
    }
  ],
  "name": "アプリ名",
  "display": "browser",
  "short_name": "アプリ名",
  "start_url": "/?ref=a2hs"
}
```

start_urlで任意のURLパラメータを指定することで、アクセス解析等でホーム画面経由でのユーザー数を計測できるようになります。

### ・HTMLからmanifest.jsonの参照

各ページのhead内でmanifestを読み込みます。

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

### ・linkタグでアイコン画像を指定

iOS Safari向けに`apple-touch-icon-precomposed`で画像URLを別途指定します。

```HTML
<link rel="apple-touch-icon-precomposed" href="/img/icon_192.png">
```



## おわりに
今回調査するまで、そもそもiOS Safariがmanifest.jsonを参照していることを知りませんでした。can i useを見る限りiOS11.3からブラウザショートカットとしてのA2HSに対応していたようです。

https://caniuse.com/web-app-manifest

ホーム画面追加だけを意識してmanifest.jsonを設定することはあまりないと思いますが、アイコン画像や飛び先URLを設定できるので忘れずに指定しておくとよさそうです。

※後日、A2HS対応の効果検証を別記事にしました。

https://qiita.com/satoru-ka/items/f3d8e68eb0ad1e6e7fb2

## 参考URL

Webアプリインストールも含めたA2HS全体の細かい仕様は以下のページが参考になります。

https://web.dev/customize-install/

https://web.dev/install-criteria/

https://web.dev/display-override/

https://web.dev/maskable-icon/

https://github.com/tecdrop/pwa-display-test