PWAをNativeAppだと錯覚させる
こんにちは、@kaa_a_zuです。PWAという単語を聞いて、皆さんは何を想像しますか?A2HS、オフライン利用、プッシュ通知など様々な機能があるかと思います。今回は、あまり知られていないけど、WebAppを確実にNativeAppに近付ける機能についてご紹介をします。また、この記事は 2021年のPWA(Progressive Web App)のアドベントカレンダー 19日目の内容になります。
私が想定している読者は、全てのWeb開発に関わる方々です。中でも「既にPWAサービスを展開している」「既存のPWAを今すぐにNativeAppに近づけたい」という開発者に届けることができたら嬉しいです。
目次
- PWA と ProjectFugu について
- マニフェストファイルの基礎
- さらにNativeAppに近付ける マニフェストファイル(2021年末版)
1. PWA と ProjectFugu について
ProjectFuguをご存知でしょうか?また、PWAとProjectFuguの関係をご存知でしょうか?
この章では、PWAとProjectFuguについて簡単に紹介をします。
ProjectFuguとは
そもそも、なぜFuguについての説明を挟んだかというと、PWAを語る上でFuguの存在を知らないといけないと考えているからです。Fuguとは 「NativeAppが持つあらゆる機能をユーザーのセキュリティ、プライバシーを維持したまま、WebAppとして実現すること」 を目的としてChromiumチームが始めたプロジェクトです。Fuguは英語ではなく、日本語のフグを指しています。フグ料理はとても美味しいものですが、フグを正しく調理しないと(毒によって)人を殺めてしまうことがあります。Chromiumチームがこの名前を選んだのは、Webの核となる考え方に背いた場合、プロジェクト全体が裏目に出る可能性があることを知っていたためです。実際にNativeとWebのギャップを埋める際には、ユーザーのセキュリティ、プライバシー、信頼など、Webの核となる考え方を維持する方法でそれを実現しようとしており、今日多くの機能をリリースしています。
FuguAPI一覧
現在提供されているFuguAPIや、提供が検討されているFuguAPIは、以下のサイト(トラッカー)で確認をすることができます。ここには、ステージ別でFuguAPIの記載がされています。
ステージは5つに分かれており、簡単に以下のようになっています。
- Under consideration(議論中)
- Started(開発中)
- Dev trial(フラグを利用すれば開発者が利用可能)
- Origin trial(開発者が申請をすればそのドメインにおいて一般ユーザーも利用可能)
- Shipped(全てのユーザーが利用可能)
一般のユーザーが機能を利用するためにはOrigin trial以上のステージにそのAPIがある必要があります。Webからデバイスのファイルシステムにアクセスする機能(FileSystemAccess)やOS起動時にPWAを立ち上げる機能(RunPWAonOSLogin)などもFuguによって提供されていることがわかるかと思います。
FuguAPIの仕組み
FuguAPIは、NativeAPIとWebの間の抽象化レイヤーとして機能しています。 インターフェースだけを知っていれば良いため、Web開発者はNativeAPIの詳細について考える必要はありません。ブラウザーは、使用しているデバイスに応じて、関連付けられたNativeAPIを呼び出します。例えば、Chrome71以降で順次各OS向けにShipされた、Nativeデバイスの共有機能を利用するためのWebShareAPI(WebShareTarget)は、以下のような構成になっています。
上記のようにブラウザが利用するNativeAPIを切り替えてくれるため、開発者はすべてのシステムで同じインターフェース(navigator.share(data)
)を呼び出します。注意が必要なのは、必要なインターフェイスが使用可能かどうかを実行時に確認するのは開発者の責任であるということです。例えば、WebShareAPIを利用する時には次のようなif文が必要になります。
if ('share' in navigator) {}
else {
// fallback処理
}
PWAとは
PWA(Progressive Web Application)とは新しいWebAPIを用いてネイティブアプリと同様の使い勝手をもたらすウェブアプリのことです。言わば、最近のデザインパターンの1つであり、イメージとしては以下の図のようにNativeとWebの良いとこどりをしているものです。
画像参照元: https://web.dev/what-are-pwas/
縦軸Capabilityは「できること」を、横軸Reachは「どれだけの人に届くか」を示しています。見ての通りNativeAppsはできることが多い反面、OSに依存している, インストールをしないといけないなどの理由でWebAppsに比べるとリーチが弱いです。WebAppsはリーチが強い反面、通知ができない, OS独自の機能を使うことができないなどできることが少ないです。PWAはこの二つの指標をどちらも満たす可能性を持つデザインパターンです。
ここで1つの疑問が湧きます。PWAというのは良さげなデザインパターンであるということは分かったけど、具体的にWebAPPがProgressiveなWebAppなのかどうかの基準は何なのでしょうか? 改めて、皆さんに質問があります。
そのWebAppがPWAであるかどうかの基準は何でしょうか? 少しだけ考えてみてください。
2. マニフェストファイルの基礎
この章では、PWAに欠かすことができないマニフェストファイルの基礎的な知識について紹介をします。まずはじめに、前章で投げた質問の答えです。「そのWebAppがPWAであるかどうかの基準」 は①マニフェストファイルがあるかどうか、②1つ以上のServiceWorkerがインストールされているかどうかです。(※1) 誤った解釈として最も多いのが「Webページがインストール可能になっているかどうか」です。A2HS(AddToHomeScreen)は、PWAを代表とする機能の1つですが、必ずしもPWAに必要という訳ではありません。「オフライン時に利用できること」や「プッシュ通知」も同様にPWAの機能であって、PWA化の基準ではありません。
それでは改めて、マニフェストの基本的な中身を見ていきます。
{
"theme_color": "#f69435",
"background_color": "#f69435",
"display": "fullscreen",
"scope": "/",
"start_url": "/",
"name": "pwa-dinosaur",
"short_name": "dino",
"icons": [
{
"src": "./icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
},
...他のアイコン
],
}
マニフェストでは、アプリの名前(name
), テーマカラー(theme_color
), アプリのアイコン(icons
), アプリケーションの起動元(start_url
), 当マニフェストの適応範囲(scope
)などを定めることができます。これらの基本的な詳細については、仕様をご確認ください。
マニフェストの中身を見ましたが、これらの内容をいちいち設定するのは面倒です。そのため、世の中には、URLからマニフェストを自動的に作成してくれるツールがいくつかあります。icons用の複数サイズ画像の生成なども行ってくれるため、これらのツールを利用して作成することがミスもなく良いかと思います。
- https://www.simicart.com/manifest-generator.html/
- https://www.pwabuilder.com/
- https://manifest-gen.netlify.app/
作成した、マニフェストを取り込むためには、以下のようにHTMLで link
を使います。IANAの仕様 に従い .webmanifest
拡張子を利用する事を個人的には推していますが、application/json
のレスポンスが返ってくるのであれば取り込むことはできるので .json
拡張子を利用しても問題はありません。
<link rel="manifest" href="./manifest.webmanifest">
<link rel="manifest" href="./manifest.json">
試しに Chromeの隠しゲームであるdino runを自作しPWA化、A2HSをした例がこちらです。
余談ですが、Chrome89で試験的にA2HSの条件に「オフライン時にstart page が200を返すこと」が追加されました。2021年12月現在は、フィードバックを受けこの条件はなくなっており、従来通り「ServiceWorker に fetch イベントがあること」となっています。ただ、将来的にA2HSの条件としてオフライン対応やPPS(PagePerfomanceScore)が追加される可能性は高いため視野に入れておくのが吉だと思います。
3. さらにNativeAppに近付けるマニフェストファイル(2021年末版)
遅くなりましたが、この章が当記事のメインになっています。ここでは 「PWAをもっとProgressiveさせる方法」 について3つの機能を紹介します。なお、紹介する3つの機能について、以下2つの前提があるためご了承をいただきたいです。
それでは、見ていきましょう。
Rich Installer
1つ目は、Rich Installerです。
概要
これは、AppStoreやGooglePlayStoreで普通のアプリをインストールする時のようなInstallerを表示することができる機能です。(※TWAのようなストアで配信をするための技術ではありません)
デモ
動画を見ていただくと、以下2つの特徴に気がつくと思います。
- スクリーンショットが掲載できる
- アプリの説明が掲載できる
「インストールする」という無機質なボタンが存在する従来と、アプリ説明+プレビュー画像が表示される当機能導入後のどちらが良いでしょうか。インストール画面をより良くすることによって、PWA化したアプリをインストール(A2HS)して貰いやすくなると思いませんか?
導入方法
manifest.webmanifest に description
と screenshots
を追記するだけで導入することができます。
{
"description": "おっす!おら「run dino」の主人公の「dinosaur」だ!\nrun dinoとは?\n\ndinosaur が ジャンプでサボテンを避けるゲームゲームだ! サボテンに当たらずに進めたスコアを競うことができるぞ!\n\n遊び方\n1.クリックしてスタート\n2.クリックでジャンプ\n3.終了時にスコアを見る",
"screenshots": [
{
"src": "./screenshots/dino-start.jpg",
"sizes": "1125x2300",
"type": "image/jpg"
}
],
...その他
}
App Shortcut
2つ目は、App Shortcutです。
概要
これは、アプリを起動する時にショートカットを使えるようにするための機能です。例えば、TwitterのようなPWAを作成していたとき「投稿する」というショートカットを定義することで、ユーザーは無駄な画面遷移をせずに投稿画面を開くことができるようになります。
デモ
動画では、ホーム画面のアプリをホールドした際に「ホーム」「ランキング」「設定」3つのショートカットメニューがアイコンと併せて表示されています。ユーザーがよく利用する機能をアプリ起動時に選択できるようにすることで無駄な遷移がなくなり、UXの向上が見込まれると思いませんか?
導入方法
manifest.webmanifest に shortcuts
を追記するだけで導入することができます。
{
"shortcuts": [
{
"name": "ホーム",
"short_name": "home",
"description": "ゲームをします",
"url": "/",
"icons": [{ "src": "./shortcuts/home-256.png", "sizes": "256x256" }]
},
{
"name": "ランキング",
"short_name": "rank",
"description": "ランキングを見ます",
"url": "/setting.html",
"icons": [{ "src": "./shortcuts/ranking-256.png", "sizes": "256x256" }]
},
{
"name": "設定",
"short_name": "setting",
"description": "設定をします",
"url": "/ranking.html",
"icons": [{ "src": "./shortcuts/settings-250.png", "sizes": "250x250" }],
...その他
}
Get things done quickly with app shortcuts
URL protocol handler
3つ目は、URL protocol handlerです。
概要
これは、AppのDeepLinkのようなもので、PWAを明示的に開くための機能です。例えば、TwitterのようなPWAを作成していたとき、ユーザーAがとあるコンテンツのシェアをする場合、この機能を用いることでシェアされたユーザーBはそのコンテンツをPWAで見ることが可能になります。現在は、デスクトップ(Mac,Windows,Chrome)でのみ機能するのですが、今後モバイルへの対応もされる予定になっています。
デモ
動画では、<a href="web+dino://">PWA Dinoを開く(Desktopでのみ動作します)</a>
の部分をクリックした際に予めPWAに定義しておいた web+dino
を起動するようにしています。
導入方法
manifest.webmanifest に protocol_handlers
を追記するだけで導入することができます。
{
"protocol_handlers": [
{
"protocol": "web+dino",
"url": "/%s" // %s は placeholder として必要になる
}
],
...その他
}
なお、このように特定のサイトにプロトコルを定義しておく別の方法として、registerProtocolHandler
があります。どちらも同様の機能を提供しますが、URL protocol handlerを用いた方が簡単に定義をすることができます。また、マニフェストに記述することでPWAと密結合になるため、より意味的になると考えています。
URL protocol handler registration for PWAs
みなさん、お気付きでしょうか?今ご紹介した3つの機能を提供するために行ったことはマニフェストファイルの修正だけです。HTMLやJavaScriptのコードには触れていません。冒頭で記述した「今すぐにNativeAppに近付ける」という文言はこういう意味で使っていました。
最後に
この記事では、「PWAをよりNativeAppに近付けるために」と題して、Fuguに関連した3つの面白い機能を紹介しました。最近では、NativeAppでしか出来なかったいくつかのことがWebでも利用できるという状況になってきています。また、FuguTrackerを見ていただくだけでも分かるように、面白い機能のWebへの導入検討がいくつかされています。これらの機能については、誰もがフィードバックをすることができるため、参画してPWA自体をProgressiveするのも面白いのではないかと思います。この執筆を通して、開発者が一丸となって全てのユーザーにより良い体験を届けることが出来るようにしていきたいと改めて思うことができました。(Appleさん、3年くらい言ってるのですが、iOS Safariでのpush通知機能搭載...お願いします)
最後になりますが、「PWAや今後のWebについて」について話しませんか? コロナ禍でオフ会みたいなのもあまりできていないため、エンジニアと話す機会を欲しています。
Discussion