ひさびさにブログを書く時間が取れたので、今ごろですが de:code 2018 で私が担当した AD09「進化する Web ~ Progressive Web Apps の実装と応用 ~」のについてのフォローアップ記事を書きます。
二日目の最終セッションにもかかわらず、ご参加くださいました皆様、誠にありがとうございました。
アンケートの内容を見るに、多くの方にご満足いただけたようで非常にうれしく思います。
この記事では、同セッションの内容について記述していきます。
進化する Web ~ Progressive Web Apps の実装と応用 ~
この記事では、昨今話題に上ることが多い PWA こと Progressive Web アプリケーションについて、実際の作り方を解説しながら、それがいったいどういったものであるかを詳(つまび)らかに紹介することを目的としています。
Web では、「ネイティブアプリと同じことができる」、「ネイティブアプリを置き換える」など、期待に胸を膨らませずにいられない浪漫に満ちた噂がありますが、それが本当かどうか記事をご覧いただくとご理解いただけると思います。
Progressive Web Apps のつくり方を紹介する前に、簡単に概要を紹介しましょう。
Progressive Web Apps とは?
Progressive Web Apps (以下 PWA と記述) は、一言でいうならば「ネイティブアプリのような UX を提供する Web アプリの概念」といったところでしょう。2015 年の 11 月に開催された Chrome Dev Summit 2015 のキーノートで発表されて話題となりました。
もともとは、その年の 10 月に Alex Russell 氏(Google) がブログ記事に投稿した、クライアントの性能に合わせて段階的に進歩する Web アプリケーションのコンセプトでした。
PWA というと、"ネイティブアプリのような体験" という特徴ばかりが注目されますが、大きな特徴がもうひとつあります。それは、PWA という名前にも含まれている Progressive というところです。
これは HTML5 が普及しはじめたころにあった、「HTML5 が解釈できるモダンブラウザーにはリッチな体験を、そうでないブラウザーには従来とおなじ体験を」というデザインの考え方 Progressive Enhancement に由来します。
PWA はこの思想を踏襲し、性能の低い Web ブラウザーを切り捨てることなく、クライアントの性能に合わせた機能提供を行います。
PWA は、性能の低い Web ブラウザーからアクセスがあった場合は従来と同じ Web ページとして動作し、PWA が動作する機能を備えた Web ブラウザーからアクセスがあった場合は、その機能を活かし、これまでの Web アプリには無かったネイティブアプリのような体験を提供します。
Progressive Web Apps を実現する機能
それでは、"これまでの Web アプリには無かったネイティブアプリのような体験" というのはどのようなものがあるでしょう?
代表的なものとしては以下の 4 つが挙げられます。
- オフラインサポート
- プッシュ通知
- バックアップグラウンド処理
- デバイスへのインストール(デバイスのホーム画面から起動できる)
これらはの機能はそれぞれ以下のような新しい API によって実現されます。
- オフラインサポート - Cache API
- プッシュ通知 - Push API
- バックアップグラウンド処理 - Background Sync
- デバイスへのインストール(OS のメニューから起動できる) - Web App Manifest
そして、これらの機能を提供しているのが 1 ~ 3 が Service Worker で、 4 が Web App Manifest です。
PWA の定義に明確なものはありませんが、上記の機能の中からオフラインサポートと、インストール(アイコンをデバイスのホーム画面に追加)機能をサポートしていれば、PWA を名乗ってもそう否定されることはないでしょう。
これらの機能により、デバイスのホーム画面から、ナビゲーションバーなどのブラウザー UI が無い状態でアプリケーションを起動し、オフラインの状態でも使用できる、という体験をユーザーに提供できます。
これらの体験は、これまでの Web アプリケーションには無かったネイティブアプリのならではのメリットと言えるでしょう。
それでは、逆に Web ならではのメリットとはなんでしょう?
Web のメリット
ネイティブアプリにはない Web ならではのメリットを、Google さんのイベントではよく以下の SLICEという言葉で表しています。
- Secure (安全)
- Linkable (リンク可能)
- Indexable (インデックス可能)
- Composable (再構成可能)
- Ephemeral (一時的な利用)
これら従来の Web とネイティブアプリの体験上のメリットを合わせたものが PWA のメリットとなります。
Progressive Web Apps が提供する価値
PWA の提供する価値について、Google さんのイベントではよく FIRE という言葉で紹介されていますが、
- Fast: パフォーマンスの良い、軽快な動作
- Integrated: OS と統合されたユーザー体験
- Reliable: オフラインでも動作する利便性と信頼性
- Engaging: Web サイトの価値向上
この記事ではもう少しかみ砕いて紹介しましょう。
発見性
PWA であれば、アプリを公開するのにアプリ ストアにわざわざお金を払ってアプリを提出したり、審査を通すための不自由なルールに縛られる必要はありません。
これまでの Web アプリと同じようにインターネットに公開しておけば、検索エンジンがクロールして見つけてくれます。
いままでの SEO のスキルがそのまま使えるうえ、Web は、アプリ ストアとは比べものにならない数のユーザーが、比べものにならないくらいの回数、常に検索を行っています。
この圧倒的なオポチュニティ(機会)の違いは、自分自身が今日何回 Web を検索したか、アプリストアを検索したか、比べてみればよくわかるでしょう。
インストール可能
PWA はさまざまなデバイスにインストール可能ですが、そのためにプラットフォームごとに違う開発言語で書き直したりパッケージンクしなおしたりする必要はありません。
PWA をサポートしている Web ブラウザーであれば、同じアプリケーションをその全部にインストールして使うことができます。
また、"インストールしなくても使える" 点もメリットです。
もともとが Web ページなので、ちょっとだけ使ってみるということが可能です。
サービスを試用してみようと思ったときに、"アプリのインストールが障壁になって利用を中断してしまった"、という経験は誰にでもあることでしょう
また、スマートフォンでコンテンツを閲覧中に、突然、アプリのストア画面が表示され、アプリのインストールを促されて不快な思いをしたこともあるかと思いますが、そういったことを避けられます。
PWA であれば提供者もユーザーもアプリのインストールについてのネガティブな点を回避することができます。
再エンゲージ可能
従来の Web ページであれば、ユーザーがコンテンツから離脱したあとは、再び訪問してくれることを祈るくらいしかできませんでしたが PWA はサーバー側から通知を Push することができます。
これによりユーザーに即時的な価値を提供できます。例えば、EC ショップであればタイムセールの開始であるとか、オークションサイトであればオークションの開始や、最高落札額の更新などです。通知機能を適切に利用することで、ユーザー側の機会獲得を増やし、再エンゲージを促すことができます。逆にどうでも良いことを通知しすぎるとユーザーの心象を害するので注意が必要です。
とくに、初めてページを訪問したユーザーに「プッシュ通知を許可しますか?」というメッセージを表示するのは避けたいところです。
ネットワーク非依存
PWA はオフラインでの使用が可能ですので、ネットワークの状態に左右されないように作ることが可能です。また、常に使用されるアセットをローカルにキャッシュすることで表示のスピードアップや、回線の使用料を減らすことにも貢献します。
プログレッシブとレスポンシブ
PWA はきちんとその思想を理解してつくれば、低機能なブラウザーや PWA をサポートしないデバイスにもサービスを提供できます。また、さまざまな画面サイズに対応するためのレスポンシブな機能については、Web には Media Queries 等、そのためのナレッジもリソースも豊富に存在するため、既存のスキルを活かして機能を実装できます。
安全
PWA は Web コンテンツと同じ Web ブラウザーの強力なサンドボックス内で動作するため、ネイティブアプリのようにユーザーの強い権限で動作して誤動作や悪意のあるコードによってシステムに深刻なダメージを与えることはありません。また https でしか動作しないためサーバーとのやりとりを安全に行うことでできます。
リンク可能
PWA はインターネット上でユニークな URL をもっており、ハイパーリンクのあるさまざまなところからサービスに接続することができます。PWA を使用するのにアプリ ストアは必要なく、面倒なインストールプロセスも必要ありません。
PWA のメリットは、Web とネイティブ アプリののメリットを合わせたということだけでなく、それらを状況に合わせて取捨選択できることです。
Progressive Web Apps を実現する API
ここからは PWA を実現するための API と、それらをどのように使ってアプリケーションを構築していくかについて紹介します。
Service Worker
PWA を実現するうえで中心となる機能を提供するのが Service Worker です。
Service Worker とはなにか?、端的に言うと、「バックグラウンドで動作する "プログラミング可能な"ネットワークプロキシ」です。
Service Worker は Web Worker の一つで、Web ページのスクリプトとは独立して動作しており、DOM にアクセスしたりすることはできませんが、Web ページのネットワーク リクエストすべてをインターセプトできます。
つまり、Web ページからのリクエストを横取りしてキャッシュしたものを返したり、改ざんしたりといったことができます。そのため localhost、127.0.0.1 接続以外は https の使用が必須となります。
Service Worker が提供する機能
Service Workerが提供する機能は主に以下の四つです。
- キャッシュ
- リクエストのハンドリング
- Push 通知
- バックグラウンド同期
これらの機能を図で紹介します。
キャッシュとリクエストのハンドリング
Service Worker は Web ページからのリクエストの中に、自分のキャッシュリストに含まれるアセットを見つけると、レスポンスからこれを取得してキャッシュします。
それ以降、Web ページからリクエストされたアセットがキャッシュ内に存在する場合は、そのキャッシュされたアセットを返します。ネットワークから取得しないので、アセットの取得は高速に完了し、通信コストは発生しません。
Push 通知
関連付けられた Web ページがアクティブでなくても、サーバーからの Push を受け取り Notification API 等を使用してユーザーに通知を行えます。
バックグラウンド同期
オフライン中にユーザーが行った操作をキャッシュし、
オンライン時にその内容を同期することができます。
このように Service Worker はプログラミング可能なネットワークプロキシとして、これまでにないさまざまな機能を提供します。
これらの機能の 2018 年 6 月時点のサポート状況は以下のとおりです。
ここからは Service Worker の具体的使い方について解説していきます。
Service Worker を使う準備
Service Worker を使った開発を行う際に用意しなければならないものがあります。
Web アプリケーション、もしくは Web コンテンツが必要です。これはけして SPA (Single Page Application) のようなアプリケーション然としたものである必要はなく、既存の一般的な Web ページであってもかまいません。
この Web ページ、もしくは Web アプリケーションは、html や css、js、や画像に代表されるメディアといった複数のファイルで構成されていると思いますが、それとはべつに Service Worker 用の JavaScript ファイルをひとつ用意します。ここでは便宜上 sw.js と名付けます。
この Service Worker 用の JavaScript ファイルは Web コンテンツ側の JavaScript コードから登録され稼働を開始します。
Service Worker は、自身のファイルが配置された以下のディレクトリに対しスコープを持つので、コンテンツ/アプリケーション全体をキャッシュするなど管理下におきたい場合は Web サイトのルートに配置します。
Service Worker の登録
Service Worker の登録は Web コンテンツの JavaScript から行います。
登録に必要なコードは非常にシンプルで、最低限、以下のコードで問題を発生させることなく Service Worker の登録が行えます。
//Service Worker がサポートされているかチェック
if (navigator.serviceWorker) {
//Service Worker を登録
navigator.serviceWorker.register('/sw.js');
}
Web コンテンツ側のコードから navigator.serviceWorker.register メソッドにより Service Worker の登録が行われると、Service Worker 用の JavaScript コード (ここでは sw.js) では install イベントが発生します。
//キャッシュするアセットのリスト
var urlsToCache = [
'/',
'/index.html',
'/css/index.css',
'/script/index.js'
];
//install イベントのハンドラ
Self.addEventListener('install', function(event) {
event.waitUntil(
//キャッシュを開く
caches.open('キャッシュの名前')
.then(function(cache) {
//アセットのリストをキャッシュに登録
return cache.addAll(urlsToCache);
}));
});
install イベントハンドラ内では、キャッシュを開き
var urlsToCache = [
'/',
'/index.html',
'/css/index.css',
'/script/index.js'
];
//install イベントのハンドラ
Self.addEventListener('install', function(event) {
event.waitUntil(
//キャッシュを開く
caches.open('キャッシュの名前')
.then(function(cache) {
//アセットのリストをキャッシュに登録
return cache.addAll(urlsToCache);
}));
});
キャッシュにアセットのリストを登録します。
var urlsToCache = [
'/',
'/index.html',
'/css/index.css',
'/script/index.js'
];
//install イベントのハンドラ
Self.addEventListener('install', function(event) {
event.waitUntil(
//キャッシュを開く
caches.open('キャッシュの名前')
.then(function(cache) {
//アセットのリストをキャッシュに登録
return cache.addAll(urlsToCache);
}));
});
Service Worker が登録され、install イベント内の処理が無事に完了すると、次に activate イベントが発生します。(もし install イベント内の処理が失敗した際には error イベントが発生します。)
e.waitUntil(
caches.keys().then(function(keyList) {
return Promise.all(keyList.map(function(key) {
if (key !== 'キャッシュの名前') {
return caches.delete(key);
}
}));
})
);
});
install イベント内で"しなければいけない処理"というものはとくにないのですが、一般的に古いキャッシュを削除するのに使用されます。このサンプルコードではキャッシュからキーの一覧を取り出し、
e.waitUntil(
caches.keys().then(function(keyList) {
return Promise.all(keyList.map(function(key) {
if (key !== 'キャッシュの名前') {
return caches.delete(key);
}
}));
})
);
});
キャッシュの名前 (新しく指定された) と比較し、異なるものをすべて削除しています。
e.waitUntil(
caches.keys().then(function(keyList) {
return Promise.all(keyList.map(function(key) {
if (key !== 'キャッシュの名前') {
return caches.delete(key)
}
}));;
})
);
});
上記サンプルコードの、"キーの一覧と新しく登録されたキャッシュの名前を比較して異なるものをすべて削除してしまう"、というやり方は少々乱暴かもしれませんので、実際に実装を行う際にはどのようにキャッシュの削除を行うかは充分に考慮してください。
なぜ activate イベントでキャッシュを削除するのか?
Service Worker 自体は、Service Worker 用の JS ファイルを更新することで再登録されますが、キャッシュが削除されるわけではありません。よって、いずれどこかのタイミングで用済みとなった古いキャッシュを削除する必要が出てきます。
たとえば、キャッシュの対象となっている index.html に更新があった場合は、更新前の index.html を保持しているキャッシュを削除しないかぎりユーザーにはいつまでも更新前の index.html が表示されることになります。
Service Worker 用の JS ファイルが更新されたあと、新しい Service Worker はバックグラウンドでインストールされますがまだ動作はしません。新しい Service Worker に制御が移るタイミングは古い Service Worker が制御しているすべてのページが閉じた後からになります。そのため install イベントで古いキャッシュを削除してしまうと、まだ動作している古い Service Worker はキャッシュを使用できなくなってしまいます。
いっぽう activate イベントではページの制御が新しい Service Worker に移っているので、古い Service Worker が使用していたキャッシュを削除することができます。
なにをキャッシュさせるか?
キャッシュさせるべきは App Shell です。App Shell はアプリケーションの UI が機能するために必要な最小限のリソースです。
App Shell をローカルにキャッシュすることで、アプリケーションの UI 表示と使用可能となるまでの時間を短縮することができ、オフラインでの使用も可能になります。
また要件に応じて、キャッシュが有効となるアセット類を指定しても良いでしょう。
しかし、なんでもキャッシュさせれば良いというものでもありません。
たとえば、WebGL ベースのゲームは、一般的に使用するアセット類のサイズが大きく、これを毎度起動する際にサーバーからダウンロードするのは、時間もかかり通信コストもかさみます。
たしかに、これらをキャッシュさせておけば、通信コストを下げ、ゲーム開始までの時間も短縮できます。
しかし、キャッシュストレージの容量には制限があり、また、cache オブジェクトの代わりに容量の大きい IndexedDB を使用したとしてもクライアントのストレージを占有することになります。
PC などのストレージ容量の大きいデバイスではあまり問題にならないかもしれませんが、スマートフォンのようなモバイル デバイスではストレージ容量を圧迫することにつながります。
よって、なにをキャッシュさせるかは充分に考慮する必要があります。
リクエストのハンドリング
Service Worker は有効化(activate)された後、アイドル状態となり Web ページからのリクエストやサーバーからの Push を待ちます。
アイドル状態のとき、制御下にある Web ページでリンクをクリックするなどしてネットワークリクエストが発生すると Service Worker では fetch イベントが発生します。
e.respondWith(
caches.match(e.request)
.then(function(response) {
return response || fetch(e.request);
}));
})
fetch イベントハンドラの引数として渡されるオブジェクトに、発生したリクエストが含まれるので、同リクエストがキャッシュ内に存在するのか調べ、
e.respondWith(
caches.match(e.request)
.then(function(response) {
return response || fetch(e.request);
}));
})
キャッシュ内にリクエストが存在すればそれを返し、存在しなければ fetch メソッドを使用してネットワークにリクエストを投げます。
e.respondWith(
caches.match(e.request)
.then(function(response) {
return response || fetch(e.request);
}));
})
それぞれの処理結果をリクエスト元の Web コンテンツ側に返します。
e.respondWith(
caches.match(e.request)
.then(function(response {
return response || fetch(e.request);
}));
})
この動作により Web コンテンツ側では Service Worker やキャッシュを意識することなく、これまで通りの方法でページの制作を行うことができます。
また既存の Web コンテンツに Service Worker の機能を追加する場合も、Service Worker を登録するためコードを追加する以外の作業は、基本的に必要ありません。
de:code 2018 のセッション動画で Service Worker を追加するデモを行っていますので、ぜひ実際の動作をご覧ください。
Web App Manifest
Web App Manifest は、デバイスのブラウザーによって [ホーム画面に追加] される際のアイコンや、ホーム画面から起動した際のスプラッシュアイコンや背景色、アプリケーションが動作するウィンドウのスタイルを定義します。
manifest は、json 形式で記述し、以下のような link タグを Web コンテンツ/アプリケーション側に追加して参照させます。
Web App Manifest については、詳しい解説が MDN にあるのでそちらを参照することをお勧めしますが、以下に簡単な説明を兼ねたサンプルを掲示します。
"lang": "ja", ← 言語
"name": "The enemy of galaxy", ← アプリケーションの名前
"short_name": "T.E.O.G", ← アプリケーションのショートネーム
"start_url": "/?utm_source=pwd", ← 開始するときの URL (※1)
"display": "standalone", ← ウィンドウのスタイル
"background_color": "black", ← 背景色
"description": "銀河に平和を取り戻すためのゲームです。", ← 説明文
"orientation": "portrait" ← 画面の向き
"icons": [{ (※2)
"src": "images/homescreen48.png", ← 画像ファイルのパス
"sizes": "48x48", ← サイズ
"type": "image/png" ← 画像の種類
}, {
"src": "images/homescreen72.png",
"sizes": "72x72",
"type": "image/png"
}]
}
(※1)Google Analytics 等を使用しているときはクエリーストリングを使用することで PWA として起動されたのか、ブラウザからページにアクセスしたのか判断が可能
(※2)iPhone や iPad でアイコンが反映されない場合は apple-touch-icon を使用
de:code 2018 のセッション動画で Web App Manifest を追加するデモを行ってぜひ実際の動作をご覧ください。
現在の Windows 10 バージョン 1803 の Progressive Web Apps の動作
なお、2018 年 6 月現在の Windows 10 バージョン 1803 (OS ビルド 17134.112) では残念ながら Web App Manifest によるウィンドウの制御は有効になりません。
たとえば Windows 10 の Microsoft Edge で Progressive Web Apps のページをタスクバーにピン留めして起動したとしても Web ブラウザーの UI を表示したまま起動してきます。
Windows 10 で Progressive Web Apps にそれらしい動作をさせるには UWP (Universal Windows Platform) アプリでラップする必要があります。
しかし、Windows 10 の次のアップデートでは、Web App Manifest の display の設定に対し、PWA のウィンドウは以下のような表示になるそうです。
マイクロソフトの Progressive Web Apps への
取り組み
Windows 10 の [Microsoft Store] から Progressive Web Apps が入手することができます。
Web App Manifest のところで書いたとおり、現在の Windows 10 にプレーンな Progressive Web Apps をインストールしても、ネイティブアプリのような外観にはなりません。そのためMicrosoft Store から入手できる Progressive Web Apps は UWP アプリにラップされています。
Microsoft ストアでの Progressive Web Apps の公開
Microsoft ストアで Progressive Web Apps を公開するには 2 つの方法があります。
1 つめが Bing による自動インデックスによる登録と、2 つめが Progressive Web Apps の提供者が Microsoft ストアに Progressive Web Apps を提出するセルフパブリッシングです。
以下でこの 2 つの方法について紹介します。
Bing による自動インデックス(BETA)
現在はまだ BETA の状態ですが、Bing が Web 上の Progressive Web Apps を検出し、レビューを行い、自動的に Microsoft ストアに公開します。
Bing に自動インデックスされるための条件は、現在のところ以下のようなものがあります。
- HTTPS, セキュアなエンドポイント
- 高品質の manifest
- オフラインサポート
- ストアの審査をパス
- デジタルグッズを販売しないこと
- アダルトコンテンツを含まないこと
- 不快なコンテンツは不可
- Windows ならではの差別化がされている
上記リストの最後の "Windows ならではの差別化がされている" というのは少しわかりづらいかもしれません。
Microsoft Store で公開される Progressive Web Apps は UWP アプリにラップされるので WinRT (Windows Runtime) API を使用することができます。
つまり WinRT API を使用することで、Windows 10 で使用した際には、純粋な Progressive Web Apps からはアクセスできないプラットプラットフォームやハードウェアリソースの機能を使用することができるため、これらを利用した機能を実装することで差別化を図ることができます。
Microsoft ストア向け Progressive Web Apps の検証
けして Progressive Web Apps の検証に限ったものでなく、ましてや Microsoft ストア向けの Web コンテンツ用に限定するものではありませんが Web サイトや Progressive Web Apps の品質をチェックするための sonarwhal というサービスが公開されています。
sonarwhal は Progressive Web Apps が Microsoft ストア向けの準備がてきているか、だけでなく、一般的な Web サイトやアプリケーションのパフォーマンスやユーザーエクスペリエンス、セキュリティの向上の役に立つ情報を提供してくれます。
Bing に検出されないようにするには
ここまで、どのように Progressive Web Apps を作れば Bing に自動的に発見されて Microsoft ストアで公開されるか、について紹介してきました。
しかし Microsoft ストアで公開されたくないということもあるでしょう。
Progressive Web Apps が以下のいずれかの条件に合致していた場合、Bing は自動インデックスを行いません。
- manifest なし
- https なし、もしくは オフラインで動作しない
- Robot.txt ファイルが設定されている
- manifest の display 設定が browser
既に Microsoft ストアで公開されているものを取り消しい場合は、アプリを削除するよう reportapp@microsoft.com宛にサービスリクエストを出します。
セルフパブリッシングによる Microsoft ストアでの公開
Bing の自動インデックスに期待するのではなく、明示的に Microsoft ストアで Progressive Web Apps を公開するにはdev.microsoft.comで開発者アカウントを取得し、パッケージ(appx)化して Microsoft ストアに提出します。アプリの内容が Microsoft ストアの審査をパスすれば Microsoft ストアで公開されます。
Progressive Web Apps をパッケージ化するには以下の方法があります。
- Visual Studio 2018 を使用する
- PWABuilder を使用する
- pwa-builder CLI を使用する
PWABuilder について
PWABuilder はインターネットにホストされているサービスで、おなじくインターネットにホストされている Web アプリケーションのための manifest ファイルや Service Worker のコード、Service Worker を登録するためのコードを生成します。
また UWP の Hosted アプリのパッケージも生成できるので、Progressive Web Apps を Microsoft ストアで公開する際にはこれをストアに提出します。
PWABuilder を使用した既存の Web アプリケーション用の manifest ファイルや Service Worker のコードを生成する手順については de:code 2018 のセッション動画のデモをご覧ください。
Windows ストア(UWP) アプリの価値
前述しましたが、Progressive Web Apps を UWP アプリ(Hosted Web アプリ)としてラップすることで WinRT が提供するすべての機能を利用することができます。
これは予定表やアドレス帳といったプラットフォームが提供するソフトウェア的なリソースはもちろん、USB やセンサー類といったハードウェアリソースも含まれます。
アプリケーションが通常の Web ブラウザー上で動作しているのか、UWP で動作しているかは JavaScript の if 文で簡単に判断できるので、WinRT API にアクセスするためのコードをインターネットでホストされているコンテンツに含めておくことができます。
if(window.Windows){
//セカンダリータイルをピン留めする
tile = new Windows.UI.StartScreen.SecondaryTile(
tileId, text, text, activationArguments,
newTileDesiredSize, logoUri);
}
JavaScript で記述した UWP から WinRT API を使用するサンプルコードは以下に豊富に用意されているので、Windows 10 限定となってしまいますが、純粋な Progressive Web Apps の機能だけでは実現できない要件がある場合は、こういった方法もあるということを覚えておくと良いかもしれません。
Visual Studio 2018 を使用して Progressive Web Apps を UWP でラップし、WindowsRT API を使用する方法については、de:code 2018 のセッション動画のデモをご覧ください。
その他、Progressive Web Apps を UWP として Microsoft ストアに公開することで、Microsoft ストアの提供するマーケティングデータ (ダウンロード数、ユーザーの性別、年齢層、国、etc..) や、決済のためのストアの API が利用できたり、人気があれば Microsoft ストアまトップページに掲示されたり、とさまざまなメリットもあります。
しかも Hosted アプリであれば、共通のコンテンツでありながら純粋なままの Progressive Web Apps が Web サイトでホストされているため、アプリストアを通さない場合のメリットも享受できます。
【参考】
・Windows デベロッパーセンター - PWAとWindows10
この記事では UWP の Hosted アプリについて紹介しましたが、Apache Cordova でもさまざまなモバイル プラットプラットフォーム向けに Hosted アプリを開発することができます。興味のある方は以下の記事をご覧ください。
・Create a hosted web app using Apache Cordova
Progressive Web Apps の価値を高める API
ここまで Windows 10 で動作する UWP アプリでラップされた Progressive Web Apps の紹介をしていましたが、ここからはふたたびプレーンな Progressive Web Apps についてです。
ここまでの説明でご理解いただけたかと思いますが、Progressive Web Apps は、「ネイティブアプリのような体験を提供する」と言っても、Web ブラウザーの機能を超えて動作することはできません。
例えば、表示速度や動作速度はネイティブアプリと比較するとどうしても劣ります。
しかし、Web ブラウザーで新しくサポートされた以下のような機能を使用すれば、その能力的な差を縮めることができます。
またこれまでの Web コンテンツには無かった新しい体験をユーザーに提供したり、決済の仕組みも Web 標準の API を使用してこれまでよりも少ない工数で組み込むことができるので、これらを使用してアプリケーションの価値を高めることができます。
- CSS3
3D Transform 関連等 GPU を使用する設定があり、これを意識的に利用することで描画速度を向上させることができます。 - WebAssembly
C 言語などで記述し、あらかじめコンパイルしたものを Web ブラウザーで動作させるため高速な計算が可能となります。 - WebVR
VR デバイスの提供する API をサポートし、ユーザーにより Immersive な体験を提供できます。 - Web Payments
決済画面その他、支払いに関する機能を提供します。これと Paypal や Stripe などが提供する決済用の API を繋げれば少ない工数で独自に決済期の機能を実装できます。自前の決済の仕組みがあれば、もうなにかを販売するたびにアプリ ストアに使用料を支払う必要はありません
この他にも、最新の Web ブラウザーにはこれまでできなかった機能が日々搭載されてきます。そういった新機能をいち早く利用できるのも、逆にレガシーな Web ブラウザーには引き算した機能を提供できるのも Progressive Web Apps の良いところです。(もちろん、そう作れば、ですが。)
Progressive Web Apps の位置づけ
PWA こと Progressive Web Apps は「ネイティブアプリのような体験を提供する」という言葉が独り歩きしてしまい、まるで「ネイティブアプリを置き換える」といった印象を持っている人も多いようです。かと言って「ネイティブアプリを置き換えることはできない」というのも真ではないでしょう。
例えば、スマートフォン アプリには、アプリとしてインストールさせるためだけに外側を Web View でラップしたいわゆる「ガワアプリ」と呼ばれるものがあります。
こういったものは今後は Progressive Web Apps に置き換えられていくでしょう。
実際にイベントサイトや、カンファレンスのセッションスケジュールの部分を PWA 化してユーザーが持ち歩けるようにしているサイトはすでにいくつか存在します。
- ABC 2018 Spring | 日本最大級のAndroidデベロッパーの祭典
- ng-japan - The Angular conference in Tokyo, Japan (2018/6/16)
こういったものも Progressive Web Apps が出てくる以前は Web ページとは別にスマートフォン用のアプリを、場合によってはプラットフォームごとに別々の言語で開発し、それぞれのアプリストアに提出して審査を受けるといったことをしていました。
Web ページとアプリの開発が共通化でき、配布の手間も掛からないということは予算や時間的にも非常に大きなメリットがあります。
しかし、Web ブラウザー内の JavaScript からアクセスできないプラットフォームの機能を利用するアプリケーションや、高速な動作や描画を必要とする用途には今後もネイティブ アプリが選択されることでしょう。
Progressive Web Apps は Web アプリケーションとネイティブアプリの体験的なメリットを受け継ぎ、ちょうどその中間に位置し、その隙間を埋めるものです。
Web のページでは poor だったもの、逆にネイティブアプリでは too much だったものが Progressive Web Apps には最適なのかもしれません。
少し作って試すだけの実装ならそれほど難しくありませんので気になる人はぜひ Progressive Web Apps を作ってみることをお勧めします。