のんラボ

自分のサイトをサクッとPWA化!PWA導入編①

2019/06/07 2019/06/07 自分のサイトをサクッとPWA化!PWA導入編①

PWAを簡単に導入するには?

最近のWEB言語界隈は流行り廃りが非常に激しいですよね。

でもこのPWAはまだまだこれからな技術!導入したい誰かのために、導入方法を簡単ではありますが、記載しておこうと思います。

基礎知識として

ServiceWorkerご存知でしょうか?

こちらGoogleのブログです。

このページにはこう記載されています。

Service Worker の紹介
リッチなオフライン体験、定期的なバックグラウンド同期、プッシュ通知など、これまでネイティブアプリを必要としていた機能が Web にもやってきます。 Service Worker はそれらの機能を提供する基盤技術です。

Service Worker とは
Service Worker はブラウザが Web ページとは別にバックグラウンドで実行するスクリプトで、Web ページやユーザーのインタラクションを必要としない機能を Web にもたらします。 既に現在、プッシュ通知やバックグラウンド同期が提供されています。 さらに将来は定期的な同期、ジオフェンシングなども導入されるでしょう。 このチュートリアルで説明する機能は、ネットワーク リクエストへの介入や処理機能と、レスポンスのキャッシュをプログラムから操作できる機能です。

Service Worker はブラウザが Web ページとは別にバックグラウンドで実行するスクリプトで」この一文がキモですよね。
要はWEBページ開いて無くても、バックグラウンドで特定の処理をしてくれるということです。ブラウザ立ち上げてないのにプッシュ通知受け取ってくれたりするのはこの子のおかげです。

manifest.jsonご存じでしょうか?

お次はこちらの公式サイト

要はこのWEBアプリの基本属性の情報をためておくファイルですね。
テーマカラーは青で・・・アプリ名は〇〇で・・・アイコンは〇〇.pngで・・・みたいな情報を格納するファイルがmanifest.jsonです。

ちなみにこのサイトのmanifest.jsonは簡単な構成です。

copied.{
    "short_name": "non's Labo",
    "name": "non's Labo",
    "display": "standalone",
    "icons": [{
            "src": "android-chrome-512x512.png",
            "type": "image/png",
            "sizes": "48x48"
        },
        {
            "src": "android-chrome-512x512.png",
            "type": "image/png",
            "sizes": "96x96"
        },
        {
            "src": "android-chrome-512x512.png",
            "type": "image/png",
            "sizes": "192x192"
        }
    ],
    "start_url": "/"
}

この構成ファイルをもとに、PWAとしてインストールする情報になっています。
上図に乗っているアイコンが、アプリアイコンとして使用され、Name属性がアプリ名として、アイコンの下に表示されます。

導入するにはこの子達の設定をすればいいだけ

  1. 読み込むべきファイルを用意します。
    manifest.json
    copied.{
     "short_name": "non's Labo",
     "name": "non's Labo",
     "display": "standalone",
     "icons": [{
             "src": "android-chrome-512x512.png",
             "type": "image/png",
             "sizes": "48x48"
         },
         {
             "src": "android-chrome-512x512.png",
             "type": "image/png",
             "sizes": "96x96"
         },
         {
             "src": "android-chrome-512x512.png",
             "type": "image/png",
             "sizes": "192x192"
         }
     ],
     "start_url": "/"
    }
    

sw.js

copied.var urlsToCache = [
    '/js/app.js'
];

self.addEventListener('install', function (event) {
    return install(event);
});

self.addEventListener('message', function (event) {
    return install(event);
});

const install = (event) => {
    return event.waitUntil(
        caches.open('laboCache')
        .then(function (cache) {
            urlsToCache.map(url => {
                return fetch(new Request(url)).then(response => {
                    return cache.put(url, response);
                });
            })
        })
        .catch(function (err) {
            console.log(err);
        })
    );
}

self.addEventListener('activate', function (e) {
    console.log('ServiceWorker activate')
})

self.addEventListener('fetch', function (event) {})
  1. 導入したいTOPページにこれを記載

    copied.<script>
    // PWA
    window.addEventListener("load", () => {
     if ("serviceWorker" in navigator) {
         navigator.serviceWorker
             .register("/sw.js")
             .then(registration => {
                 console.log("ServiceWorker registered");
                 registration.onupdatefound = function() {
                     console.log("Exist update");
                     registration.update();
                 };
             })
             .catch(error => {
                 console.warn("ServiceWorker error", error);
             });
     }
    });
    </script>
    
  2. 同様にheadタグ内でmanifest.jsonを読み込み

    copied.<!-- PWA -->
    <link rel="manifest" href="/manifest.json">
    

解説

sw.jsについて

sw.jsこれはなにかというと、WEBページがアクティブじゃないときに走る処理です。

copied.// インストールされたとき
self.addEventListener('install', function (event) {});
// アクティベートしたとき
self.addEventListener('activate', function (event) {});

など、様々なイベントを検知して、バックグラウンド実行してくれます。
他にもイベントはたくさん用意してありますし、これ用のサードパーティ製ライブラリも存在します。
私達はこれを駆使してオフライン対応や、通知イベントを発火したりします。

上に書かれているような内容ではconsole.logでログ吐き出しているので、オフライン対応もへったくれも無いですね。

PWA導入「ホームボタンへ追加」について

copied.<script>
// PWA
window.addEventListener("load", () => {
    if ("serviceWorker" in navigator) {
        navigator.serviceWorker
            .register("/sw.js")
            .then(registration => {
                console.log("ServiceWorker registered");
                registration.onupdatefound = function() {
                    console.log("Exist update");
                    registration.update();
                };
            })
            .catch(error => {
                console.warn("ServiceWorker error", error);
            });
    }
});
</script>

そのページがロード完了したらserviceWorkerを起動させてregisterでインストール処理を走らせます。クリックされればthenが走ります。
また、このページにアクセスするたびに、registration.onupdatefound でキャッシュのアップデートがないか確認します。ある場合(つまりjavascriptが変更されている場合やcssが変更されている場合)はregistration.update();で更新処理が動作します。これでキャッシュの中身を入れ替えてバージョンを管理しています。

ここに表示されているのが、manifest.jsonの内容ですね。

headで読み込みするのを忘れずに

scriptmanifest.json読み込みできなければ上の図のようなボタンは発生しません。
ご注意を!

最後に

改めて読み返し見ると、わかりにくい箇所が何点かありますね・・・
これは今後記事の更新をしていくとしましょう!
この記事が参考に慣れば幸いです。