プログレッシブ ウェブアプリを、ウェブサイトではなく「本物」のアプリのように感じさせる
プログレッシブ ウェブアプリの流行語ビンゴをプレイするときは、「PWA は単なるウェブサイトである」と安心できる。Microsoft の PWA に関するドキュメントは同意しており、このサイトでも説明しています。また、PWA のノミネータである Frances Berriman と Alex Russell もそのように書いています。はい。PWA は単なるウェブサイトですが、それだけではありません。うまくいけば、PWA はウェブサイトではなく「本物」のアプリのように感じられます。では、本物のアプリのように感じられるとはどういう意味でしょうか。
この質問に答えるために、Apple Podcasts アプリを例に考えてみましょう。パソコンの macOS とモバイルの iOS(および iPadOS)で利用できます。Podcasts はメディア アプリケーションですが、ここで紹介した基本的な考え方は他のカテゴリのアプリにも当てはまります。
オフラインでの実行可能
一歩引いて、スマートフォンやデスクトップ パソコンに搭載されているプラットフォーム固有のアプリケーションを考えてみると、明らかに目立つ点が 1 つあります。それは、何も取得されないということです。Podcasts アプリでは、オフラインの場合でも常に何かが表示されます。ネットワークに接続されていなくても、アプリは自然に開きます。[ランキング] セクションにはコンテンツが表示されず、[現在接続できません] のメッセージに [再試行] ボタンが表示されます。あまり快適ではないかもしれませんが、ある程度満足しています。
Podcasts アプリは、いわゆる App Shell モデルを採用しています。左側のメニュー アイコンやコア プレーヤー UI アイコンなどの装飾画像を含め、コアアプリを表示するために必要なすべての静的コンテンツがローカルのキャッシュに保存されます。ランキング データなどの動的コンテンツはオンデマンドでのみ読み込まれます。読み込みが失敗した場合は、ローカルのキャッシュに保存された代替コンテンツを利用できます。このアーキテクチャ モデルをウェブアプリに適用する方法については、App Shell モデルの記事をご覧ください。
オフライン コンテンツを利用可能、メディアを再生可能
オフラインのときも、左側のドロワーから [Downloaded] セクションに移動できます。ダウンロードしたポッドキャストのエピソードはすぐに再生でき、アートワークや説明などのすべてのメタデータとともに表示されます。
以前にダウンロードしたメディア コンテンツは、Workbox ライブラリのキャッシュに保存された音声と動画を提供するレシピを使用して、キャッシュから配信できます。その他のコンテンツは常にキャッシュまたは IndexedDB に保存できます。詳細と、どのストレージ テクノロジーをどのような場合に使用するかについては、ウェブ用のストレージの記事をご覧ください。使用可能なメモリ量が少なくなったときにパージされるリスクなしに、永続的に保存する必要があるデータがある場合は、Persistent Storage API を使用できます。
バックグラウンドでのプロアクティブなダウンロード
オンラインに戻ったら、もちろん「http 203
」のようなクエリでコンテンツを検索できます。検索結果に登録すると、質問なしで HTTP 203 ポッドキャストというシリーズの最新エピソードがすぐにダウンロードされます。
ポッドキャスト エピソードのダウンロードは、処理に時間がかかる可能性があります。Background Fetch API を使用すると、ダウンロードをブラウザに委任できます。ブラウザはバックグラウンドでダウンロードを処理します。Android では、ブラウザがダウンロードをオペレーティング システムに委任することもできるため、ブラウザを継続的に実行する必要はありません。ダウンロードが完了すると、アプリの Service Worker が起動し、レスポンスの処理方法を決定できます。
他のアプリと共有、他のアプリとやり取りする
Podcasts アプリは他のアプリと自然に統合されます。たとえば、気に入ったエピソードを右クリックすると、デバイス上のメッセージ アプリなどの他のアプリと共有できます。また、システム クリップボードにも自然に組み込まれます。エピソードを右クリックして、リンクをコピーできます。
Web Share API と Web Share Target API を使用すると、デバイス上の他のアプリとの間でテキスト、ファイル、リンクを共有および受信できます。ウェブアプリでオペレーティング システムに組み込まれた右クリック メニューにメニュー項目を追加することはできませんが、デバイス上の他のアプリとの間でリンクする方法は他にもたくさんあります。Async Clipboard API を使用すると、テキストと画像データ(PNG 画像)をプログラムでシステム クリップボードに書き込むことができます。Android では、Contact Picker API を使用して、デバイスの連絡先マネージャーからエントリを選択できます。プラットフォーム固有のアプリと PWA の両方を提供する場合は、Get Installed Related Apps API を使用して、プラットフォーム固有のアプリがインストールされているかどうかを確認できます。この場合、ユーザーに PWA のインストールを促したり、ウェブプッシュ通知を受け入れたりする必要はありません。
アプリのバックグラウンド更新
ポッドキャスト アプリの設定で、新しいエピソードを自動的にダウンロードするようアプリを設定できます。そのようなことを考える必要すらありません。更新されたコンテンツが常にそこにあります。魔法です。
Periodic Background Sync API を使用すると、アプリを実行しなくても、バックグラウンドでコンテンツを定期的に更新できます。つまり、新しいコンテンツが事前に利用可能になるため、ユーザーは決断したらすぐに詳しく調べることができます。
クラウド経由で状態を同期
それと同時に、所有するすべてのデバイスで定期購入が同期されます。シームレスな世界では、ポッドキャストの登録チャンネルを手動で同期させる必要がありません。同様に、モバイル デバイスのメモリが、パソコンですでに視聴したエピソードによって消費されることを心配する必要はありません。再生状態は同期され、再生したエピソードは自動的に削除されます。
アプリの状態データの同期は、Background Sync API に委任できるタスクです。同期処理自体はすぐに行う必要はなく、最終的にのみ行う必要があり、ユーザーがすでにアプリを再度閉じたときに行う場合もあります。
ハードウェア メディア キー コントロール
たとえば、Chrome ブラウザでニュースページを閲覧しているときなど、別のアプリケーションで忙しいときでも、ノートパソコンのメディアキーで Podcasts アプリを操作できます。 早送りや巻き戻しのためにアプリに切り替える必要はありません。
メディアキーは Media Session API でサポートされています。ユーザーは、物理キーボードやヘッドフォンのハードウェア メディアキーを使用したり、スマートウォッチのソフトウェア メディアキーからウェブアプリを操作したりできます。シーク操作をスムーズにするためのもう 1 つの方法として、開始クレジットや章の境界を渡すなど、ユーザーがコンテンツの大部分をシークしたときにバイブレーション パターンを送信することもできます。
マルチタスクとアプリのショートカット
もちろん、いつでもどこからでもポッドキャスト アプリにマルチタスクを実行できます。アプリのアイコンがはっきりわかるので、デスクトップやアプリケーション ドックに配置すれば、気軽にポッドキャストをすぐに開始できます。
プログレッシブ ウェブアプリは、パソコンとモバイルのどちらからでも、ホーム画面、スタート メニュー、アプリケーション ドックにインストールできます。 インストールは、プロアクティブなプロンプトに基づいて行うことも、アプリ デベロッパーが完全に制御することもできます。知っておくべきポイントはすべて、インストール可能にするための要件の記事に記載されています。 マルチタスクの場合、PWA はブラウザから独立しているように見えます。
コンテキスト メニューでのクイック操作
アプリでよく使う操作である新しいコンテンツの [検索] や [新しいエピソードの確認] には、Dock のアプリのコンテキスト メニューからアクセスできます。[オプション] メニューから、ログイン時にアプリを開くこともできます。
PWA のウェブアプリ マニフェストでアプリアイコンのショートカットを指定すると、ユーザーがアプリアイコンから直接アクセスできる一般的なタスクへのクイックルートを登録できます。macOS などのオペレーティング システムでは、ユーザーがアプリアイコンを右クリックして、ログイン時にアプリが起動するように設定することもできます。ログイン時に実行の提案に関する作業が進行中です。
デフォルト アプリとして動作
podcasts://
URL スキームを利用することで、他の iOS アプリやウェブサイトやメールもポッドキャスト アプリと統合できます。ブラウザで podcasts://podcasts.apple.com/podcast/the-css-podcast/id1042283903
などのリンクをクリックすると、Podcasts アプリがすぐに開き、ポッドキャストの登録や再生を選択できます。
完全なカスタム URL スキームの処理はまだ不可能ですが、PWA 向けの URL プロトコル処理の提案に向けて取り組みが進行中です。現時点では、web+
スキーム接頭辞を持つ registerProtocolHandler()
が最適な代替手段です。
ローカル ファイル システムの統合
そのように思われるかもしれませんが、Podcasts アプリはローカル ファイル システムと自然に統合されています。ポッドキャストのエピソードをダウンロードすると、ノートパソコンでは ~/Library/Group Containers/243LU875E5.groups.com.apple.podcasts/Library/Cache
に保存されています。たとえば、~/Documents
とは異なり、このディレクトリは通常のユーザーが直接アクセスするためのものではありませんが、存在します。ファイル以外のストレージ メカニズムについては、オフライン コンテンツのセクションで説明しています。
デベロッパーは File System Access API を使用して、デバイスのローカル ファイル システムにアクセスできます。直接使用することも、API をサポートしていないブラウザに対して透過的にフォールバックを提供する browser-fs-access サポート ライブラリを介して使用することもできます。セキュリティ上の理由から、システム ディレクトリはウェブアクセスできません。
プラットフォームのデザイン
Podcasts のような iOS アプリでは、もっと明白なことがあります。どのテキストラベルも選択できず、すべてのテキストがパソコンのシステム フォントに溶け込んで表示されます。また、選択したシステムカラーテーマ(ダークモード)も尊重されます。
none
の値を指定して user-select
CSS プロパティを利用すると、UI 要素が誤って選択されないように保護できます。ただし、このプロパティを悪用してアプリのコンテンツを選択不能にすることは避けてください。ボタンのテキストなどの UI 要素にのみ使用してください。font-family
CSS プロパティの system-ui 値を使用すると、アプリに使用するシステムのデフォルト UI フォントを指定できます。アプリは、ユーザーの prefers-color-scheme
選択を尊重し、オプションのダークモードの切り替えでオーバーライドできます。もう 1 つの決定すべきことは、たとえば、カスタムの「プルして更新」を実装する場合など、スクロール領域の境界に達したときのブラウザの動作です。これは、CSS プロパティ overscroll-behavior
で行うことができます。
カスタマイズされたタイトルバー
Podcasts アプリのウィンドウを見ると、Safari ブラウザ ウィンドウなど従来の統合されたタイトルバーとツールバーはなく、メインのプレーヤー ウィンドウにドッキングされたサイドバーのようにカスタマイズされたエクスペリエンスであることがわかります。
現時点ではできませんが、現在、タイトルバーのカスタマイズに取り組んでいます。ただし、ウェブアプリ マニフェストの display
プロパティと theme-color
プロパティを指定することで、アプリ ウィンドウのデザインを決定し、どのデフォルトのブラウザ コントロールを表示しないかを決定できます。
テンポの良いアニメーション
ポッドキャストのアプリ内アニメーションはテンポよく滑らかです。たとえば、右側の [エピソードのメモ] ドロワーを開くと、見やすくスライドして表示します。一時保存したエピソードから 1 つのエピソードを削除すると、残りのエピソードがフローティングして、削除したエピソードによって解放された画面領域を消費します。
アニメーションとパフォーマンスの記事で説明されているさまざまなベスト プラクティスを検討すれば、ウェブで高パフォーマンスのアニメーションを実現できます。ページ分けされたコンテンツやメディア カルーセルで一般的に見られるスクロール アニメーションは、CSS のスクロール スナップ機能を使用すると、大幅に改善できます。完全に制御するには、Web Animations API を使用します。
コンテンツがアプリ外に表示される
iOS の Podcasts アプリは、実際のアプリ以外の場所にコンテンツを表示できます。たとえば、システムのウィジェット ビューに、Siri の候補の形式でコンテンツを表示できます。タップ 1 回で反応できる、利用状況に基づいた積極的な行動を促すフレーズを使用すると、ポッドキャストのようなアプリの再エンゲージメント率を大幅に高めることができます。
Content Index API を使用すると、アプリはオフラインで使用できる PWA のコンテンツをブラウザに伝えることができます。これにより、ブラウザはメインアプリの外部にこのコンテンツを表示できるようになります。アプリ内の興味深いコンテンツを音声再生に適したものとしてマークアップし、構造化マークアップ全般を使用することで、検索エンジンや Google アシスタントなどの仮想アシスタントが、理想的な形でサービスを提示できるようになります。
ロック画面のメディア コントロール ウィジェット
ポッドキャスト エピソードの再生中は、Podcasts アプリのロック画面に美しいコントロール ウィジェットが表示されます。このウィジェットには、エピソードのアートワーク、エピソードのタイトル、ポッドキャスト名などのメタデータが表示されます。
Media Session API を使用すると、アートワークやトラックのタイトルなどのメタデータを指定できます。指定したメタデータは、ブラウザのロック画面、スマートウォッチ、その他のメディア ウィジェットに表示されます。
プッシュ通知
プッシュ通知は、ウェブ上ではやや煩わしさが増しました(通知プロンプトの表示はかなり静かになりました)。しかし、適切に活用すれば、多くの価値を付加できます。たとえば、iOS Podcasts アプリでは、登録しているポッドキャストの新しいエピソードの通知や新しいエピソードのおすすめ、アプリの新機能に関する通知を任意で受け取ることができます。
Push API を使用すると、アプリでプッシュ通知を受信して、PWA に関する重要なイベントについてユーザーに通知できます。将来の既知の時刻に呼び出される通知で、ネットワーク接続を必要としない場合は、Notification Triggers API を使用できます。
アプリアイコンのバッジ
登録しているポッドキャストで新しいエピソードが利用できるようになると、Podcasts のホーム画面アイコンにアプリアイコン バッジが表示され、邪魔にならない方法でアプリの利用を再開してくれます。
Badging API を使用して、アプリアイコンのバッジを設定できます。これは、PWA に「未読」の概念がある場合や、ユーザーの注意をアプリに呼び戻す手段が必要な場合に特に役立ちます。
メディアの再生は省エネ設定よりも優先されます
ポッドキャスト メディアの再生中は、画面がオフになることがありますが、システムはスタンバイ モードになりません。 アプリでは、歌詞や字幕を表示するなど、必要に応じて画面をスリープ解除することもできます。
Screen Wake Lock API を使用すると、画面がオフになるのを防ぐことができます。ウェブ上でのメディア再生により、システムがスタンバイ モードに入ることを自動的に阻止します。
アプリストアでアプリを見つける
Podcasts アプリは macOS のデスクトップ エクスペリエンスの一部ですが、iOS では App Store からインストールする必要があります。podcast
、podcasts
、apple podcasts
をクイック検索すると、すぐに App Store のアプリが表示されます。
Apple は App Store での PWA を許可していませんが、Android では、信頼できるウェブ アクティビティでラップされた PWA を送信できます。これは、bubblewrap
スクリプトで簡単に行えます。このスクリプトは、PWABuilder の Android アプリのエクスポート機能を内部的に使用するためにも使用されています。この機能は、コマンドラインに触れることなく使用できます。
機能の概要
以下の表に、すべての機能を簡潔にまとめた概要と、それらをウェブで実現する際に役立つリソースのリストを示します。
おわりに
PWA は、2015 年に導入されて以来、大きな進化を遂げました。プロジェクト Fugu 🐡? において、会社をまたぐ Chromium チームは、残りわずかなギャップの解消に取り組んでいます。 この記事で紹介しているアドバイスを少しでも実践するだけで、アプリのような感覚に少しずつ近づき、ユーザーは「ウェブサイトだけ」にしか対処していないことを忘れさせることができます。正直なところ、ユーザーのほとんどは、実際のアプリのように感じられるのであれば、アプリがどのように構築され、なぜそうすべきかは気にしていないからです。
謝辞
この記事は、 Kayce Basques、 Joe Medley、 Joshua Bell、 Dion Almaer、 Ade Oshineye、 Pete LePage、 Sam Thorogood、 Reilly Grantand、Reilly Grantand によってレビューされました。