PWA（Progressive Web Application）に対応するために最低限やったこと

# Progressive Web Applicationの入門編として、最低限対応するためにすべきことをメモとしてまとめました。

まずは、PWAに対応することを目的にしております。プッシュ通知の実装は次回書く予定です。
さっそく、説明に入りたいと思います。

## PWAとは
PWA（ Progressive Web Application ）とは、簡単にいうとスマートフォンでWebサイトをアプリのように使うことができるものです。

> 詳細な説明はこちら
<a href="https://developers.google.com/web/fundamentals/codelabs/your-first-pwapp/" target="_blank"> Your First Progressive Web App  |  Web  |  Google Developers </a>

以前からスマートフォンブラウザには、『ホーム画面に追加』という機能がありました。

以前の機能は、ホーム画面にアイコンが追加され、そのアイコンをクリックするとブラウザでそのサイトが開けるというもので、スマホ版ブックマークのような印象でした。

それが改良され、アイコンをクリックすると、ブラウザのフレーム（例えばURLバーなど）をなくしてネイティブアプリのような見せ方ができたり、プッシュ通知を送ることができるものになりました。これがPWAです。

Javascriptでネイティブアプリっぽい実装をすることができる『ionic』などのフレームワークは、この機能を取り入れ始めています。

## PWA対応方法

PWAの対応は、ほとんどJavascriptで完了します。

なので、ウェブサイトとして公開されているものであれば対応させることができます。

### 対応までのステップ
1. manifest.jsonを作成する
2. Service Worker用のJSファイルを作成する
3. Service Workerをサイト内からJavascriptで呼び出す
4. （おまけ）リンクの調整


## 1. manifest.jsonを作成する
manifest.jsonはその名の通り、宣言ファイルです。

ホーム画面に追加した時の名前を設定したり、ホーム画面のiconはどの画像を使用するか、などを宣言しておくものです。

ちなみに、manifest.jsonは慣習的にこの名前にしていますが、名前が異なっていても正しく呼び出せていれば名前は変更しても問題ありません。

> manifest.jsonについて詳しく知りたい方はこちら
<a href="https://developers.google.com/web/fundamentals/web-app-manifest/" target="_blank">Web App Manifest</a>

ルールとして下記の２つは含んでおく必要があります。

- short_name: ユーザーのホーム画面でテキストとして使用します
- name: ウェブアプリのインストール バナーに使用します

また、アプリとして表示したい場合は、下記の項目も含んでおいた方が良いと思います。

- start_url: ホーム画面からアプリケーションを立ち上げたとき最初にアクセスさせるURLです
- display: standalone か browser を選択可能で、standaloneにすると、ブラウザのフレームが非表示になります

```manifest.json
{
  "name": "App Name",
  "short_name": "short name",
  "icons": [{
      "src": "images/ico/apple-touch-icon.png",
      "sizes": "128x128",
      "type": "image/png"
    }, {
      "src": "images/ico/apple-touch-icon.png",
      "sizes": "144x144",
      "type": "image/png"
    }, {
      "src": "images/ico/apple-touch-icon.png",
      "sizes": "152x152",
      "type": "image/png"
    }, {
      "src": "images/ico/apple-touch-icon.png",
      "sizes": "192x192",
      "type": "image/png"
    }, {
      "src": "images/ico/apple-touch-icon.png",
      "sizes": "256x256",
      "type": "image/png"
    }],
  "start_url": "/index.html",
  "display": "standalone",
}
```

ファイルを作成できたら、PWAに対応したいウェブサイトのディレクトリに入れておいてください。

```
# フォルダのツリー構造イメージ

pwa_application
├── manifest.json
└── index.html
```

## 2. Service Worker用のJSファイルを作成する
Service Worker とは、Web Workerの１つでブラウザがWebサイトを表示しているスレッドとは別のスレッドで動いているスクリプトで、プッシュ通知やキャッシュなどの機能を提供するものです。

> Service Worker の詳細な説明はこちら
<a href="https://developers.google.com/web/ilt/pwa/introduction-to-service-worker" target="_blank">Introduction to Service Worker  |  Web   |  Google Developers</a>

Service Workerには、デバッグ用のコードだけ記載しておけば良いと思います。

```service-worker.js
self.addEventListener('install', function(e) {
  console.log('[ServiceWorker] Install');
});

self.addEventListener('activate', function(e) {
  console.log('[ServiceWorker] Activate');
});
```

こちらは、作成したら、PWAに対応したいフォルダに入れておいてください。
例えば、サイト全体ならルートディレクトリに、もし、/productでのみ有効にしたければ、/productに配置してください。

## 3. Service Workerをサイト内からJavascriptで呼び出す
Service Workerを配置したら、Webページ内からJavascriptで呼び出す必要があります。
HTMLのHeadの中に下記のような記述を追加してください。

```html
<head>
    <script>
        // この記述を追記
        if ('serviceWorker' in navigator) {
        navigator.serviceWorker
                 .register('/service-worker.js') // ここはservice-worker.jsのパスを指定
                 .then(function() { console.log('Service Worker Registered'); });
        }
        // この記述を追記　ここまで
    </script>
</head>
```

これで実装は完了です。
モバイルでWebサイトでアクセスしてホーム画面へ追加後、立ち上げてみてください。

## （おまけ）リンクの調整
実際は、これで対応完了なのですが、リンクが意外と面倒でした。
私の実装時は、サイト上のリンクをクリックすると、ブラウザが立ち上がってしまう現象が起こっていました。
調べると、このようなGistを見つけたので、参考までに共有しておきます。

```js
// https://gist.github.com/kylebarrow/1042026
// Mobile Safari in standalone mode
if (('standalone' in window.navigator) && window.navigator.standalone) {
    window.addEventListener('load', function() {
        var links = document.links,
            link,
            i;
        for (i = 0; i < links.length; i++) {
            // Don't do this for javascript: links
            if (!~(link = links[i]).href.toLowerCase().indexOf('javascript')) {
                if('href' in link && link.href.indexOf('http') !== -1 && link.href.indexOf(document.location.host) !== -1)
                {
                    link.addEventListener('click', function(event) {
                        event.preventDefault();
                        document.location.href = this.href;
                    }, false);
                }
            }
        }
    }, false);
}
```

# 所感
PWAは、まだまだ発展段階の技術ではありますが、現段階ですでに有用で、今後よりユーザーの利便性を開発コストを抑えながら向上させるためには知っておくべき技術になると感じています。
Appleも正式に対応することを発表していて、プッシュ通知への対応も来年2018年の夏頃には完了するようです。