ふとしたきっかけがあって PWA(Progressive Web Application) を作る機会がありました。今回は PWA の中でも特にキャッシュ機能を試すことが主目的だったのですが、最低限の機能を実装して公開してみたので、興味ある方は以下を参照して使ってみてください。


【PWA とは】
主に Google 主導で進められているモバイル端末向けウェブアプリケーションの技術で、「モバイル端末でウェブアプリケーションを利用する際に、ネイティブアプリであるかのような UI や動作を可能にする」ことを主目的としています。

なお PWA 自体の説明をすることが本ブログエントリの目的ではないし、そこまで含めてしまうと長くなりそうなので、興味ある方は適当にググってください。


【アプリの内容とシステム構成】
PWA には特徴的な機能がいくつかありますが、今回は特に「キャッシュ機能」を確認するためのアプリケーション実装を行いました。実際のアプリ(パズルゲーム)を使うにはスマートフォンのブラウザで以下の URL にアクセスしてください:
https://pwa-slidegame.mybluemix.net/


正しくアクセスすると以下のような画面が表示されます:
2020020301


このままアプリの実行を続けてもいいのですが、せっかくの PWA なので「インストール」してみます。メニューから「ホーム画面に追加」を選びます(下図は iPhone Safari での場合):
2020020302


正しく追加できるとホーム画面に以下のようなアイコンが追加され、次回からはここをタップすることで同じアプリを起動できるようになります。というわけでこちらをタップします:
2020020303


先程に似た画面が表示されます。ただアドレスバーなどは表示されておらず、PWA として起動してネイティブアプリっぽく起動しています:
2020020304


「(カテゴリーを選択)」と書かれた部分をタップすると、この後選択する画像のカテゴリー一覧が表示されます。実際には色々なカテゴリーがあっていくつか試すこともできるのですが、キャッシュの説明のため以下は「こども」カテゴリーを選択したものとして(それ以外のカテゴリーは選択していないものとして)説明を続けます:
2020020305


カテゴリーを選択すると、「いらすとや」の選択したカテゴリーの画像がカルーセル表示されます。画像を右や左にフリックすることで次の画像や前の画像を表示できます:
2020020306


カルーセルから「パズルにしたい画像」を選んでタップします。では↓の画像を選んでタップしたものとして以下を続けます:
2020020307


すると選択した画像が 4x4 のスライドパズル化され、実際に遊ぶことができるようになります:
2020020308


(簡単なパズルではないのですが・・)パズルを進めていって、完成すると、・・・
2020020309


パズル完成までに要した時間と動かした回数が表示されます:
2020020310


続いて過去の(回数の少ない)トップ10が表示されます。直近の記録がこの中に含まれていれば強調表示される、というゲームです:
2020020311


ここまではネットワークに接続された状態で行いました。PWA ではデータをキャッシュすることで、オフラインでもある程度の利用が可能になります。その部分を試してみましょう。この時点で起動していた PWA アプリをいったん終了(タスク一覧から終了)しておいてください。

まずはスマホをオフライン状態にします。WiFi もモバイルデータも接続されていない OFF の状態に設定します:
2020020312


あらためてホーム画面のアイコンからアプリを起動します。先程起動した時に表示されたトップページは自動的にキャッシュされていて、ネットワーク接続がなくても表示され、カテゴリー選択状態になります:
2020020313


カテゴリーとして「こども」を選択した場合も先程の実行時にキャッシュできているので、ネットワーク接続がないにも関わらず画像含めて表示することができています。なお、ここで表示されているのはあくまでキャッシュに含まれている画面であって、ネットワーク接続時の最新状態が表示されているわけではありません:
2020020314


しかし先程選択しなかったカテゴリー(例えば「職業」)を選択すると、こちらの内容は接続状態でのキャッシュが存在していないため、カルーセルの中身を取得することができず、何も表示されない、という状況になります。ある意味でキャッシュが有効に動いていることが確認できます:
2020020315


またオフラインでもパズルクリアまではできますが、その後のデータ記録目的での HTTP POST には失敗します:
2020020401



といったオフライン時にキャッシュ済みのデータを使って一部動かすことができるようになるのが PWA のキャッシュ機能です。


この PWA アプリケーションは以下のようなシステム構成となっています。構成そのものはウェブアプリケーションのシステム構成そのもので、この中で「いらすとや」のページをリアルタイムにスクレイピングしてカテゴリー一覧やカテゴリーの画像一覧を取り出して、アプリケーションの中で利用しています。アプリケーションそのものにキャッシュの機能は含まれていません:
2020013101



【PWA でのキャッシュの実現方法】
アプリケーションを PWA 化する際にいくつか設定のためのファイルを追加するのですが、それらの準備が完了していると、以下のような仕組みでキャッシュが(自動的に)実現されます。

まず、キャッシュデータが全くない状態でオフライン操作することはできません。画像とか API の実行結果とか以前に、トップページの HTML がないと何も表示できません。つまりオフラインでキャッシュ表示するためにはオンライン時にある程度の情報をキャッシュしておく必要があります。PWA では オンライン時に HTTP GET する際のパスとその結果を自動的にキャッシュします。上述の説明で行った流れをキャッシュの中身を意識した上で再度理解しておきましょう:
2020013102


そしてスマホがオフラインとなった後に PWA を起動すると、キャッシュの中身を使いながらオフラインで動作します:
2020013103


ただ(オフラインなので当然ですが)キャッシュにない HTTP GET は使えませんし、HTTP POST でデータをサーバーに送信することもできません:
2020013104


このアプリケーションのソースコードはこちらで公開しています。Node.js 上で動かすことができますが、PWA として稼働させるには HTTPS アクセスが必須となります。実際に自分のサーバーで PWA として動かす場合は HTTPS アクセスできるサーバーへデプロイしてお使いください:
https://github.com/dotnsf/pwa-slidegame