LoginSignup
30
30

More than 3 years have passed since last update.

PWA(Progressive Web Apps)を最低限で試してみる

Last updated at Posted at 2019-07-16

概要

PWAアプリを広く浅く最低限で試してみた記録です。

参考記事:PWAとは?

PWA(Progressive Web Apps)とは?メリットと実装事例について
外部の人にはいつもこの記事みせてます

開発したもの

https://dev.elephancube.jp/201907pwatest/
更新:2019/7/18

下準備

https対応の領域を準備する

https://dev.elephancube.jp/201907pwatest/
レンタルサーバーのフリーSSLです。

アイコン画像を512*512で準備する

透過が反映されるかの確認で、周りは透明、円の外周は半透明になっています。
pwa_icon.png

1. アプリ登録とオフラインで使えるまで

表示するHTMLファイル

追記していきますが、ベースはこのくらい

index.html
<!doctype html>
<html lang="ja">

<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!--PWA動作用マニフェスト-->
    <link rel="manifest" href="manifest.json">
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
        integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

    <title>PWAのテスト</title>
</head>

<body>
    <div class="container">
        <h1>PWAのテスト</h1>
        <p>更新:2019/7/5</p>
    </div>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
        integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
        crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
        integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
        crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
        integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
        crossorigin="anonymous"></script>
    <!--PWA動作用スクリプト-->
    <script src="pwatest.js"></script>
</body>

</html>

Manifestの作成(+アイコンの自動生成)

Web App Manifest Generator
このサイトを使って入力します。

190705_pwa_1.PNG

生成されたデータ

manifest.json
{
  "name": "PWAのテストアプリケーション",
  "short_name": "PWA TEST",
  "theme_color": "#2196f3",
  "background_color": "#2196f3",
  "display": "fullscreen",
  "orientation": "portrait",
  "Scope": "/201907pwatest/",
  "start_url": "/201907pwatest/index.html?m=pwa",
  "icons": [
    {
      "src": "images/icons/icon-72x72.png",
      "sizes": "72x72",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-96x96.png",
      "sizes": "96x96",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-128x128.png",
      "sizes": "128x128",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-144x144.png",
      "sizes": "144x144",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-152x152.png",
      "sizes": "152x152",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-384x384.png",
      "sizes": "384x384",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "splash_pages": null
}

ウェブアプリマニフェスト
記述の詳細は、こちらのサイトが分かりやすいです。

Service Workerの設定

PWAをもっと簡単に初めてみる
このあたりの記事を参考に、まずは、Service Workerの設定ファイルを以下のように作成。
※ なお、このファイルに、index.htmlからリンクする必要はありません。

sw.js
//キャッシュ名
var CACHE_NAME  = "PW-TEST-190705-01";

//キャッシュするファイル名
var urlsToCache = [
    "index.html",
    "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css",
    "https://code.jquery.com/jquery-3.3.1.slim.min.js",
    "https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js",
    "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js",
    "pwatest.js"
];

//インストール時処理
self.addEventListener('install', function(event) {
    event.waitUntil(
        caches
        .open(CACHE_NAME)
        .then(function(cache){
            return cache.addAll(urlsToCache);
        })
    );
});

// フェッチ時のキャッシュロード処理(2019/07/18 更新)
self.addEventListener('fetch', function(event) {
    event.respondWith(
        caches
            .match(event.request)
            .then(function(response) {
                if(response){
                    return response;
                }
                return fetch(event.request);
            })
    );
});

次に、上記ファイルをロードする JavaScript を index.html に書きます。
今回は、index.html からリンクしている pwatest.js に記述しています。

pwatest.js
$(function(){
    //Service Workerの登録
    if ('serviceWorker' in navigator) {
        navigator.serviceWorker.register('sw.js')
        .then(
        function (registration) {
                if (typeof registration.update == 'function') {
                        registration.update();
                }
        })
        .catch(function (error) {
            console.log("Error Log: " + error);
        });
    }
});

ここまでの確認

Chrome の Developer Tool で確認

190705_pwa_2.PNG
Application → Manifest

  • htmlからリンクされていないと、ここに表示がされません。
  • start_url のパス間違いなどがあると、ここでエラー表示されます。

190705_pwa_3.PNG
Application → Service Workers

  • htmlからリンクされていないと、ここに表示がされません。
  • キャッシュファイルが足りていない(記述漏れがある)と、オフラインで閲覧できない旨のエラーがでます。

Progressive Web App のデバッグ
Developer Toolsでの確認については、このサイトに詳しくのっています。

Android9.0 実機で確認

※各種メッセージが英語なのは、端末の表示言語を英語にしているためです。
2019-07-06 00.26.27.jpg
ポップアップがでて、
2019-07-06 00.26.44.jpg
インストール確認画面がでて、
2019-07-06 00.27.27.jpg
インストールされました。アイコンの透過も効いてる。
2019-07-06 00.27.38.jpg

フルスクリーンで起動しました!
その後、5分以上たってから2回目のアクセスをするとキャッシュが効きますので、オフラインにしても動作します。

iOS12.3実機で確認

IMG_0004.png
Androidのように自動でポップアップが出ることはない。
IMG_0005.png
ホームに追加から、アイコン追加。
IMG_0006.png
このときのリンク名やURLはマニフェストからの情報が反映されます。
IMG_0007.png
が...アイコンが、未設定状態
IMG_0008.png
起動すると、きちんとPWAのURLでアクセスされます。
オフラインでも動作しました。

Designing Native-Like Progressive Web Apps For iOS
iOSでアイコンを正しく設定するのは、PWAは関係なくhtmlのタグで apple-touch-icon の設定をします。このサイトのを参考に180x180のアイコン(透過なし)を設定します。

その他参考サイト
https://webdesign-trends.net/entry/7251

2.キャッシュの動作確認

キャッシュされたことが確認できた後、ファイルを更新してみます。

環境 htmlファイルを更新 jsファイルを更新
Windows10 Chrome リロードすると、内容更新される リロードすると、内容更新される
Android 9.0  PWAアプリ再起動すると、内容更新される PWAアプリ再起動しても更新されない
iOS PWAアプリ再起動しても更新されない PWAアプリ再起動しても更新されない

都合良く、ネット繋がっていたら更新してくれるということは期待できなさそう。

強制的にキャッシュを更新する

Service Worker
こちらの記事にある postMessage を使えば良さそう。

sw.js へ追記

sw.js
//メッセージを受け取ったとき
self.addEventListener('message', function(event) {
    switch (event.data) {
        case 'updateCache':
            event.waitUntil(
                caches
                .open(CACHE_NAME)
                .then(function(cache){
                    return cache.addAll(urlsToCache);
                })
            );
        break;
    }
});

html側にボタンとスクリプト追記

index.html
        <button class="btn btn-primary" id="btn_update">キャッシュ更新</button>

pwatest.js
    $('#btn_update').click(function(){
        navigator.serviceWorker.controller.postMessage('updateCache');
        setTimeout(function(){
            location.reload();
        });
    });


これで、ボタンを押した瞬間にファイルが更新され、リロードすることが確認できました。

その他参考サイト
https://blog.htmlhifive.com/2018/08/27/pwa-cache-update/

3.Webアクセスかアプリアクセスかの判別

manifest.json
  "start_url": "/201907pwatest/index.html?m=pwa",

こんな感じでURLパラメータを付与したので、それで判別します。
判別法ロジックが雑ですが、以下のような形で判別できます。

pwatest.js
    //PWAかどうかの判別
    var str = location.search;
    if(str.indexOf('m=pwa')==-1){
        //WEB MODE
    }else{
        //PWA MODE
    }

4.リンク挙動とアラートの検証

いくつかリンクを作って検証

<p><a class="btn" href="https://www.google.com/">GOOGLE(外部サイト)</a></p>
<p><a class="btn" href="page2.html">PWAスコープ内(キャッシュなし)</a></p>
<p><a class="btn" onclick="alert('アラートのテスト');">ALERT</a></p>

Android9.0 実機で確認

2019-07-17 01.24.43.jpg

スコープ内のリンク
2019-07-17 01.25.00.jpg
通常のリンクと同じく遷移。
2019-07-17 01.25.23.jpg
ただしオフラインだと当たり前だが表示されない。

スコープ外のリンク
2019-07-17 01.24.50.jpg
明示的にターゲット指定など何もしなくても、アプリ内ブラウザが起動して表示される。わかりやすい!

2019-07-17 01.25.06.jpg
アラートはWEBと同じ。

iOS12.3で確認

スコープ内のリンク
IMG_0012.png
ページ遷移。
IMG_0014.png
オフラインだとエラー

スコープ外のリンク
IMG_0010.png
プリ内ブラウザが立ち上がるが…左上に「完了」ボタンがない。
7/18追記:ServiceWorkerのfetchイベントの記述を少し変えたら、初回から「完了」ボタン出るようになった。謎。
IMG_0011.png
1ページ遷移すると「完了」ボタンがでてくる。わかりづらい。

IMG_0013.png
アラートはWEBと同じ。

5.Ajax通信の検証

同じスコープ内にapiを置いてアクセスしたら、ふつうにAJAX通信ができないことが判明!後日解決を図る。
7/18追記:Service Workerが分かっていなかった。記述を修正して動くようになりました。

参考資料メモ

PWAをもっと簡単に初めてみる
PWA対応で実装したことまとめ (実物あり)
PWA: ServiceWorkerを使って、キャッシュをコントロールする(オフラインハンドリング)
iOS 12.2のPWA対応まとめ
ScrapboxでのServiceWorkerとCacheの活用
Service Workerを使った消極的なキャッシュ
Debugging ServiceWorker

30
30
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
30