GatsbyでPWA対応～webアプリをネイティブアプリっぽく～

# はじめに
以前リリースした、弓道部専用のwebアプリをPWA化したので、その方法をまとめておきます。
[HitRate](https://hitrate.site)↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467535/72042e9b-a33c-f32f-680b-5514e8f414f6.png)

# PWAとは
PWA（Progressive Web Apps）とは、webサイトやwebアプリをネイティブアプリのようにふるまわせることができる技術です。PWAのメリット、デメリットなどは、こちらの記事が分かりやすく紹介していますのでご覧ください。
[PWA 入門 〜iOS SafariでPWAを体験するまで〜 2019年7月更新](https://qiita.com/umamichi/items/0e2b4b1c578e7335ba20)

この記事では、**GatsbyベースのサイトをPWA化する方法**を紹介します。


# 実際にできたこと
先にPWAにより実装できたことを紹介しておきます。
 **- ブラウザツールバーの色指定（androidのみ）
- ホーム画面から起動したときの背景色の指定（androidのみ）
- ホーム画面に追加催促のボトムバーの表示（androidのみ、iosは現状、各自ホーム画面に追加する必要がある）*androidにおいての出現条件は２回以上のアクセスがあり、そのアクセスに 5 分以上の間隔がある。
- ホーム画面のアイコン画像の指定
- アドレスバー非表示による大画面表示
- ホーム画面追加時のタイトルとリンクの自動入力
- オフライン対応
- キャッシュ保持によるページ表示の高速化
- PCにインストール** 

<img width="300" alt="2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467535/9b16f75b-6954-b8fd-9ae0-baeb578c28b6.png">

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467535/ef1da0ba-41fa-53f4-aef6-ccba198d578f.png)

<img width="300" alt="2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467535/bbf0bb06-f03b-d5f4-39f0-418cabd06d72.jpeg">


#PWA化する方法（Gatsbyベース）
PWA化するためには、次の三つを行う必要があります。

 **・SSL化
・Webアプリマニフェストの生成
・ServiceWorkerを有効にする** 

#### **1、SSL化** 
SSL化は、ServiceWorkerを利用するために必要です。
サイトはhttpsでアクセスできるようにしておきます。

#### **2、 Web App Manifestの生成** 
 Web App Manifestの生成のために、gatsby-plugin-manifestプラグインをインストールします。

インストールコマンド：`npm install gatsby-plugin-manifest`
（＊Gatsbyの[スターター](https://github.com/gatsbyjs/gatsby-starter-default)では、すでにgatsby-plugin-manifestプラグインが導入済みです。）

Web App Manifestは、Webアプリに関する情報(名前, アイコン, 説明など)をブラウザを提供するJSONファイルとなります。これを設定することで、webアプリをネイティブアプリのように見せることができます。

 **gatsby-config.jsの設定** 
gatsby-config.jsには、こんな感じで書き込みます。

```gatsby-config.js
plugins:[
//...
{
  resolve: `gatsby-plugin-manifest`,
  options: {
    name: `webアプリ名`,
    short_name: `webアプリ名`,
    description: `素晴らしいアプリです`,
    start_url: `/?homescreen`,
    background_color: `#ffffff`,
    theme_color: `#40c246`,
    display: `standalone`,
    icon: `src/images/icon.png`,//アイコンのpathを指定
   },
 },
//...
]

```
各オプションの説明

- name：アプリの名前を指定します。アイコンのlabelなどに利用されます。
- short_name：nameを表示するのに十分なスペースがない場合に利用されます。
- description：アプリの説明を書きます。
- start_url：アプリの開始URLを指定します。"/"でもよいが、"/?homescreen"とすることでアナリティクスで分析しやすくなるかと思います。
- background_color：ブラウザの背景色を指定します。(現状androidのみ反映される)
- theme_color：ブラウザツールバーの色を指定します。(現状androidのみ反映される)
- display：表示モードを指定する。browser, minimal-uiなどあるが、通常はstandaloneでいいと思います。
それぞれの違いはこちらのサイトが参考になりました。[PWAのmanifest.jsonで「display」の指定による表示の違い](https://code.st40.xyz/article/923)
- icon：512x512のJPEG、PNG、WebP、TIFF、GIF、またはSVGの画像を指定します。manifestファイルでは、配列で複数のサイズのiconを指定する必要がありますが、gatsby-plugin-manifestは、自動で違ったサイズのiconを生成してくれます。

#### **3、ServiceWorkerを有効にする** 

ServiceWorkerを有効にするために、gatsby-plugin-offlineプラグインをインストールします。

インストールコマンド：`npm install gatsby-plugin-offline`
（＊Gatsbyの[スターター](https://github.com/gatsbyjs/gatsby-starter-default)では、すでにgatsby-plugin-offlineプラグインが導入済みです。）

ブラウザのキャッシュを使って、オフラインでもアプリを閲覧できるようになります。API通信を頻繁にするアプリは、そんなに恩恵がないですが、キャッシュで動くため、ページの表示を高速化できます。また、今回は実装していないので取り上げませんが、Push通知もできるようになります。ただ、現状iosは未対応です。

ServiceWorkerについてもっと知りたい方は、こちらの記事が分かりやすく紹介していますのでご覧ください。
[Service Workerがもつ圧倒的な力。SEO担当者は変化に適応が必要](https://webtan.impress.co.jp/e/2019/09/02/33637)

 **gatsby-config.jsの設定** 
gatsby-config.jsにこのように書き込みます。

```gatsby-config.js
plugins:[
//...
`gatsby-plugin-offline`,
//...
]
```
#反映の確認方法
 Web App Manifestの設定が正しくブラウザに読み込まれているかは、Chrome（PC版）のDeveloper Toolsから確認することができます。
右クリック > 検証 > Application > Manifest　に詳細が載っています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467535/2f629e6f-92c4-3e87-d555-14157f811dfc.png)


#Azure StorageでホスティングしてるサイトをPWA化する時の注意点
Azure StorageでホスティングしているサイトをPWA化するためには注意が必要です。
ブラウザにmanifestファイルのMIMEタイプを理解させるために、[web.config](https://docs.microsoft.com/ja-jp/aspnet/core/host-and-deploy/iis/web-config?view=aspnetcore-5.0)に`<mimeMap fileExtension=".webmanifest" mimeType="application/manifest+json" />`を記述する必要があります。

既定では、IISは、コア設定でMIMEマップが関連付けられていないファイルを提供しません。
そのため、.webmanifestファイル拡張子を適切なMIMEタイプにマップする必要があるみたいです。
（[W3C](https://w3c.github.io/manifest/#media-type-registration)によると、マニフェストファイルのレスポンスは Content-Type: application/manifest+jsonを返すように推奨されています。）

```web.config
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <system.webServer>
        <staticContent>
            <remove fileExtension=".json" />
            <mimeMap fileExtension=".json" mimeType="application/json" />
            <mimeMap fileExtension=".webmanifest" mimeType="application/manifest+json" />//必須
        </staticContent>
    </system.webServer>
</configuration>
```

私は、azureでホスティングしてるときにこれに気づかず、ずっとpwaに対応できていませんでした(T . T)

ちなみに、こちらの記事に沿ってIISの設定からでも.webmanifestのMIMEタイプを定義することができます。
[IIS Webサイトで.webmanifestファイルを適切に提供するにはどうすればよいですか？](https://ja.ojit.com/so/iis/4093549)

#参考サイト
この記事は以下の情報を参考にして執筆しました。
[GatsbyでPWA対応](https://takumon.com/2018/10/08/)
[Progressive Web Apps (PWAs)](https://www.gatsbyjs.com/docs/progressive-web-app/)
[PWAのmanifest.jsonで「display」の指定による表示の違い](https://code.st40.xyz/article/923)
[Google ウェブアプリマニフェスト](https://web.dev/add-manifest/)
[GatsbyサイトをPWA対応する方法](https://dev.akito.io/posts/gatsby-pwa)
[Service Workerがもつ圧倒的な力。SEO担当者は変化に適応が必要](https://webtan.impress.co.jp/e/2019/09/02/33637)
[Yahoo! JAPANトップページ（スマートフォン）におけるPWAの取り組み〜ホーム画面追加編〜
](https://techblog.yahoo.co.jp/advent-calendar-2018/yahoo-toppage-a2hs/)[ウェブアプリマニフェスト](https://developer.mozilla.org/ja/docs/Web/Manifest)
[Web App Manifest W3C Editor's Draft 24 February 2021](Web App Manifest
W3C Editor's Draft 24 February 2021)