最近、プログレッシブ ウェブアプリについて多くの議論が交わされています。まだ比較的新しいモデルですが、その原則は、Vanilla JS、React、Polymer、Angular などのフレームワークで構築されたアプリを同様に強化できます。この記事では、独自のプログレッシブ ウェブアプリを今すぐ作成するためのオプションと参照アプリについて説明します。
プログレッシブ ウェブアプリとは
プログレッシブ ウェブアプリはどこでも動作しますが、最新のブラウザではさらに高速に動作します。プログレッシブ エンハンスメントはモデルのバックボーンです。
Aaron Gustafson は、段階的な拡張を M&M のピーナッツに例えています。ピーナッツがコンテンツ、チョコレート コーティングがプレゼンテーション レイヤ、JavaScript がハードキャンディのシェルです。このレイヤの色は、使用するブラウザの機能によって異なる場合があります。また、エクスペリエンスも異なる場合があります。
キャンディー シェルは、多くのプログレッシブ ウェブアプリ機能を配置できる場所と考えてください。ウェブとアプリの長所を組み合わせたエクスペリエンスです。ブラウザのタブで初めてアクセスしたユーザーに便利で、インストールは不要です。
ユーザーがこれらのアプリを繰り返し使用することで関係を築くと、キャンディーシェルがさらに魅力的になります。たとえば、(サービス ワーカーのおかげで)低速なネットワーク接続でも非常に高速に読み込まれ、関連するプッシュ通知が送信され、ユーザーのホーム画面に優先アイコンが表示され、全画面アプリ エクスペリエンスとして読み込まれます。また、スマートなウェブアプリ インストール バナーを利用することもできます。

プログレッシブ ウェブアプリは
- プログレッシブ - プログレッシブ エンハンスメントをコアテナントとして構築しているため、どのブラウザを選択してもすべてのユーザーが利用できます。
- レスポンシブ - パソコン、モバイル、タブレットなど、あらゆるフォーム ファクタに適合します。
- 接続に依存しない - Service Worker で拡張されるため、オフラインや低品質のネットワーク上でも作業可能です。
- アプリのような - アプリシェル モデルを使用して、アプリスタイルのナビゲーションとインタラクションを実現します。
- 最新 - サービス ワーカーの更新プロセスにより、常に最新の状態です。
- 安全 - TLS 経由で提供されるため、スヌーピングを防ぎ、コンテンツが改ざんされていないことを確認できます。
- 検出可能 - W3C マニフェストとサービス ワーカーの登録スコープにより、検索エンジンが見つけることができるため、「アプリケーション」として識別できます。
- 再エンゲージメントが可能 - プッシュ通知などの機能を使用して、簡単に再エンゲージメントできるようにします。
- インストール可能 - ユーザーが、アプリストアを利用することなく、最も便利なアプリをホーム画面に「保持」できるようにします。
- リンク可能 - URL 経由で簡単に共有でき、複雑なインストールは不要です。
プログレッシブ ウェブアプリは Android 版 Chrome に固有のものではありません。下記は、Android 版 Firefox(ベータ版)で動作する Pokedex プログレッシブ ウェブアプリです。初期の「ホーム画面に追加」機能とサービス ワーカーのキャッシュ機能が正常に動作しています。

このモデルの「プログレッシブ」な性質の良い点の一つは、ブラウザ ベンダーがより優れたサポートをリリースするにつれて、機能を段階的に利用可能にできることです。もちろん、Pokedex などのプログレッシブ ウェブアプリは、Android 版 Opera でも問題なく動作します。ただし、実装にはいくつかの顕著な違いがあります。

プログレッシブ ウェブアプリについて詳しくは、Alex Russell によるプログレッシブ ウェブアプリを紹介する元のブログ投稿をご覧ください。Paul Kinlan は、プログレッシブ ウェブアプリに関する非常に便利な Stack Overflow タグも作成しています。
原則
ウェブアプリ マニフェスト
マニフェストを使用すると、ウェブアプリをユーザーのホーム画面にネイティブ アプリのように表示できます。これにより、アプリを全画面モード(URL バーなし)で起動できます。また、画面の向きを制御できます。Android 版 Chrome の最新バージョンでは、スプラッシュ画面とアドレスバーのテーマカラーの定義がサポートされています。また、前述のスプラッシュ画面とホーム画面のアイコンに使用するサイズと密度でアイコンセットを定義するためにも使用されます。

マニフェスト ファイルのサンプルは、ウェブ スターター キットと Google Chrome のサンプルで確認できます。Bruce Lawson 氏が作成した マニフェスト ジェネレータや、Mounir Lamouri 氏が作成した便利な ウェブ マニフェスト バリデータもぜひご覧ください。
個人的なプロジェクトでは、realfavicongenerator を使用して、ウェブアプリ マニフェストと iOS、デスクトップなどで使用する両方のアイコンのサイズを正しく生成しています。favicons Node モジュールも、ビルドプロセスの一環として同様の出力を生成できます。
Chromium ベースのブラウザ(Chrome、Opera など)は現在、ウェブアプリ マニフェストをサポートしています。Firefox はサポートを積極的に開発しており、Edge は検討中としています。WebKit/Safari では、この機能を実装する意向について、まだ公開情報は投稿されていません。
詳しくは、ウェブの基礎のAndroid 版 Chrome のウェブアプリ マニフェストを使用したインストール可能なウェブアプリをご覧ください。
「ホーム画面に追加」バナー
Android 版 Chrome では、サイトをホーム画面に追加する機能が長い間サポートされていますが、最近のバージョンでは、ネイティブのウェブアプリのインストール バナーを使用して、サイトを事前に追加することを提案することもできます。

アプリ インストール プロンプトを表示するには、アプリが次の条件を満たしている必要があります。
- 有効なウェブアプリ マニフェストがあること
- HTTPS で配信される(無料の証明書については letsencrypt をご覧ください)
- 有効なサービス ワーカーが登録されている
- 2 回訪問し、訪問の間隔が 5 分以上ある
アプリ インストール バナーのサンプルが多数用意されています。基本的なバナーから、関連アプリの表示など、より複雑なユースケースまでカバーしています。
オフライン キャッシュ用の Service Worker
サービス ワーカーは、ウェブページとは別にバックグラウンドで実行されるスクリプトです。イベント(サービングするページから行われたネットワーク リクエストなど)に応答します。サービス ワーカーの存続期間は意図的に短く設定されています。
イベントを受信すると起動し、イベントの処理に必要な時間だけ実行されます。サービス ワーカーを使用すると、Cache API を使用してリソースをキャッシュに保存し、ユーザーにオフライン エクスペリエンスを提供できます。
サービス ワーカーはオフライン キャッシュに適していますが、サイトやウェブアプリへの再訪問時にコンテンツを即座に読み込むことで、パフォーマンスを大幅に向上させることもできます。アプリシェルをキャッシュに保存してオフラインで動作させ、JavaScript を使用してコンテンツを入力できます。

包括的な Service Worker のサンプルは、Google Chrome のサンプルで入手できます。Jake Archibald のオフライン クックブックは必読です。また、サービス ワーカーを初めて使用する場合は、Paul Kinlan の最初のオフライン ウェブアプリのチュートリアルを試すことを強くおすすめします。
また、サービス ワーカーのセットアップにかかるオーバーヘッドを削減するために役立つ、サービス ワーカーのヘルパー ユーティリティやビルドツールも多数用意されています。サービス ワーカー ライブラリにリストされています。主なものは次の 2 つです。
- sw-precache: ウェブアプリ シェルのプリキャッシュに役立つ Service Worker スクリプトを生成するビルド時ツール
- sw-toolbox: 使用頻度の低いリソースのランタイム キャッシュを提供するライブラリ
Jeff Posnick は、sw-precache に関するクイック ガイド「オフライン ファースト、高速、sw-precache モジュール」と、同じツールに関するcodelab を作成しました。
Chrome、Opera、Firefox はすべてサービス ワーカーのサポートを実装しており、Edge は、この機能への関心について肯定的な公開シグナルを示しています。Safari では、1 人のエンジニアが提案した5 年計画で、この機能に関心があることを簡単に言及しています。
再エンゲージメントのためのプッシュ通知
つまり、ユーザーがタブの外で操作できるウェブアプリを作成できます。ブラウザを閉じていても、ウェブアプリを積極的に使用していなくても、ユーザーはエクスペリエンスを利用できます。この機能を使用するには、前述の機能の一部をベースに、Service Worker とウェブアプリ マニフェストの両方が必要です。
Push API は Chrome で実装されており、Firefox では開発中、Edge では検討中です。Safari がこの機能を実装する意向を表明したという情報はまだありません。
オープンウェブでのプッシュ通知は、Matt Gaunt によるプッシュの設定に関する包括的な入門書です。また、プッシュ通知の Codelab もウェブの基礎で利用できます。

Chrome チームの Michael van Ouwerkerk が、動画で Push について説明する6 分間の紹介動画も公開しています。
高度な機能のレイヤリング
ウェブアプリの表示に使用されているブラウザによって、ユーザー エクスペリエンスの甘さのレベルが異なる場合があります。ハードキャンディのシェルはご自身で管理できます。
ウェブ プラットフォームに追加される機能(バックグラウンド同期(ウェブアプリが閉じている場合でもサーバーとの間でデータの同期を行う)やウェブ Bluetooth(ウェブアプリから Bluetooth デバイスと通信する)など)も、この方法でプログレッシブ ウェブアプリに重ねて追加できます。
ワンショット バックグラウンド同期は Chrome で有効になりました。Jake Archibald は、オフラインの Wikipedia アプリの動画と、その動作を示す記事を公開しています。François Beaufort は、この API を試すための Web Bluetooth のサンプルも提供しています。
フレームワークに優しい
上記の原則を、現在構築している既存のアプリケーションやフレームワークに適用することは可能です。プログレッシブ ウェブアプリの構築時に考慮すべきその他の原則としては、ユーザー中心のパフォーマンス モデルである RAIL と FLIP ベースのアニメーションがあります。
2016 年には、プログレッシブ ウェブ アプリケーションのサポートをコア機能として有機的に組み込んだボイラプレートとシード プロジェクトが増えることを期待しています。それまでは、これらの機能を独自のアプリに追加するハードルはそれほど高くなく、私見では、努力する価値があります。
アーキテクチャ
プログレッシブ ウェブアプリ モデルを「オールイン」で実装する方法にはさまざまなレベルがありますが、一般的なアプローチの 1 つは、アプリケーション シェルを中心にアーキテクチャを構築することです。これは必須ではありませんが、いくつかのメリットがあります。
アプリケーション シェル アーキテクチャでは、アプリケーション シェル(ユーザー インターフェース)をキャッシュに保存してオフラインで動作させ、JavaScript を使用してコンテンツを入力することを推奨しています。ユーザーが繰り返し訪問した場合、最終的にコンテンツがネットワークから取得される場合でも、ネットワークを使用せずに有意なピクセルをすばやく画面に表示できます。これにより、パフォーマンスが大幅に向上します。

Jeremy Keith 氏は最近、このようなモデルでは、サーバーサイド レンダリングをフォールバックではなく、クライアントサイド レンダリングを拡張機能として捉えるべきだとコメントしています。これは妥当なフィードバックです。
アプリケーション シェル モデルでは、サーバーサイド レンダリングを可能な限り使用し、サービス ワーカーがサポートされている場合にエクスペリエンスを「拡張」するのと同じように、クライアントサイドの漸進的レンダリングを拡張機能として使用する必要があります。最終的にこの問題に取り組む方法は数多くあります。
アーキテクチャに関する Google の記事を読み、類似の原則を独自のアプリケーションとスタックにどのように適用するのが最適かを評価することをおすすめします。
スタートガイドのボイラープレート
アプリケーション シェル
app-shell
リポジトリには、アプリケーション シェル アーキテクチャのほぼ完全な実装が含まれています。バックエンドは Express.js で記述され、フロントエンドは ES2015 で記述されています。
モデルのクライアント側とサーバー側の両方をカバーしており、かなり複雑なため、コードベースに慣れるまでに時間がかかります。現時点では、プログレッシブ ウェブアプリの最も包括的な出発点です。このプロジェクトでは、次にドキュメントに取り組みます。
ポリマー スターター キット
Polymer ウェブアプリの公式スタートガイドでは、次のプログレッシブ ウェブアプリの機能をサポートしています。
- ウェブ アプリケーション マニフェスト
- Chrome for Android スプラッシュ画面
- Platinum SW 要素を使用した Service Worker のオフライン キャッシュ
- プラチナ プッシュ要素を使用したプッシュ通知(手動設定が必要)

現在のバージョンの PSK では、一部のプログレッシブ ポリマー ウェブアプリで使用されている高度なパフォーマンス パターン(アプリケーション シェルモデル、非同期読み込みなど)がサポートされていません。
Google は、2016 年にこれらのパターンを PSK に組み込むことを目標としていますが、この点に関する初期のテストは、Rob Dodson による Polymer の Zuperkulblog アプリと、Eric Bidelman による優れた Polymer のパフォーマンス パターンに関する講演で確認できます。
ウェブ スターター キット
新しいバニラ プロジェクトの開始点として、Google は次のプログレッシブ ウェブアプリ機能を推奨しています。
- ウェブ アプリケーション マニフェスト
- Chrome for Android スプラッシュ画面
- sw-precache によるサービス ワーカーの事前キャッシュ
独自の JS/ES2015 で作業することを好み、Polymer を使用できない場合は、Web Starter Kit を参照してコード スニペットを再利用または盗用できます。
フレームワークありとフレームワークなしのプログレッシブ ウェブアプリ
コミュニティのメンバーによって、JS ライブラリやフレームワークの有無にかかわらず、すでに多くのオープンソースの Progressive Web Apps が構築されています。ヒントを得たい場合は、以下のリポジトリを参考にしてください。優れたアプリでもあります。

標準の JavaScript
- Paul Lewis の ボイスメモは、
app-shell
に似たアーキテクチャを使用して構築されています(詳細)。 - ジェイク アーチボルドによる オフライン ウィキペディア(動画)
- Paul Kinlan による Air Horner
- ギター チューナー(Paul Lewis 作)(記事)
Polymer
- Rob Dodson の Zuperkulblog(スライド)
対応
Virtual-DOM
Angular.js
- Kenneth Auchenberg の Timey.in - リソースの事前キャッシュに
sw-precache
も使用
おわりに
前述のとおり、プログレッシブ ウェブアプリはまだ初期段階ですが、その背後にある手法に触れて、独自のウェブアプリにどれだけ適用できるかを確認する絶好の機会です。
Paul Kinlan は現在、プログレッシブ ウェブアプリに関するウェブ ファンダメンタルズのガイダンスの計画を進めています。取り上げてほしい分野についてご意見がありましたら、このスレッドにコメントをお寄せください。