<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:series="http://organizeseries.com/"
	>

<channel>
	<title>えーじ &#8211; HTML5Experts.jp</title>
	<atom:link href="/agektmr/feed/" rel="self" type="application/rss+xml" />
	<link>https://html5experts.jp</link>
	<description>日本に、もっとエキスパートを。</description>
	<lastBuildDate>Sat, 07 Jul 2018 03:14:05 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.7.19</generator>
	<item>
		<title>プログレッシブウェブアプリ詳解 ─ 過去・現在・未来</title>
		<link>/agektmr/20527/</link>
		<pubDate>Wed, 14 Sep 2016 00:00:03 +0000</pubDate>
		<dc:creator><![CDATA[えーじ]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[システム開発]]></category>
		<category><![CDATA[Progressive Web Apps]]></category>
		<category><![CDATA[Service Worker]]></category>

		<guid isPermaLink="false">/?p=20527</guid>
		<description><![CDATA[連載： Web技術でアプリ開発2016 (5)Web技術でアプリ開発2016特集・第5弾は、プログレッシブウェブアプリ (Progressive Web Apps)をご紹介させていただきます。 はじめに プログレッシブウ...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/web-based-apps-2016/" class="series-391" title="Web技術でアプリ開発2016" data-wpel-link="internal">Web技術でアプリ開発2016</a> (5)</div><p>Web技術でアプリ開発2016特集・第5弾は、プログレッシブウェブアプリ (Progressive Web Apps)をご紹介させていただきます。</p>

<p><style>
.youtube {
    height: 0;
    position: relative;
    padding-bottom: 56.25%;
    overflow: hidden;
    margin-bottom: 24px;
}
.youtube > iframe {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
}
</style></p>

<h2>はじめに</h2>

<p>プログレッシブウェブアプリ(Progressive Web Apps)という言葉が初めて登場したのは2015年8月のAlex Russellによる記事<a href="https://medium.com/@slightlylate/progressive-apps-escaping-tabs-without-losing-our-soul-3b93a8561955" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Progressive Web Apps: Escaping Tabs Without Losing Our Soul</a>です。当時オフラインやプッシュ通知など、モバイルウェブを飛躍的に進化させる画期的な機能が次々と追加されていた状況において、このムーブメントを呼称するための言葉が求められていました。Google社内でいくつもの候補が挙げられましたが、Service Workerの発案者としてAlex Russellが推したのが、この「プログレッシブウェブアプリ」でした。</p>

<p>また、当初Googleで始まったプログレッシブウェブアプリの動きではありましたが、先日の<a href="https://www.youtube.com/playlist?list=PLNYkxOF6rcIAWWNR_Q6eLPhsyx6VvYjVb" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Progressive Web App Dev Summit</a>ではMicrosoft、Mozilla、Opera、Samsungの代表者も登壇するなど、各ブラウザベンダーとも足並みが揃いつつあります。これはもはやウェブ全体の動きと言うことができます。</p>

<p>若干古い情報になりますが、以降この (長い) 記事を読む以外に手早く情報を得るための方法として、下記を挙げておきます。</p>

<h3>スマートフォン体験を一歩先へ &#8211; プログレッシブウェブアプリの作り方</h3>

<div class="youtube">

<!-- iframe plugin v.4.3 wordpress.org/plugins/iframe/ -->
<iframe style="width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;" src="https://www.youtube.com/embed/VHN2wJWi0WE?controls=2&amp;modestbranding=1&amp;showinfo=0&amp;utm-source=crdev-wf" class="devsite-embedded-youtube-video" allowfullscreen data-video-id="hmqZxP6iTpo" data-autohide="1" data-modestbranding="1" data-controls="2" data-utm-source="crdev-wf" data-showinfo="0" frameborder="0" width="100%" height="500" scrolling="yes"></iframe>

</div>

<p><a href="https://www.youtube.com/watch?v=VHN2wJWi0WE" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">講演動画</a></p>

<div class="youtube">

<!-- iframe plugin v.4.3 wordpress.org/plugins/iframe/ -->
<iframe src="https://docs.google.com/presentation/d/1VcXsKDaCUpf2SS35WNcrKslkK6PcXxWsnhcKiLfWCXs/embed?start=false&amp;loop=false" width="100%" height="500" scrolling="yes" class="iframe-class" frameborder="0"></iframe>

</div>

<p><a href="https://docs.google.com/presentation/d/1VcXsKDaCUpf2SS35WNcrKslkK6PcXxWsnhcKiLfWCXs/pub?start=false&amp;loop=false&amp;delayms=3000" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">プレゼン資料</a></p>

<h2>プログレッシブウェブアプリとは</h2>

<p>プログレッシブウェブアプリとは、最新の標準ウェブ技術を用いることで、オフラインやプッシュ通知といったこれまでよりも一次元上のユーザー体験をもたらすウェブアプリのことです。必ずしもデスクトップのウェブアプリや、ページ遷移を使ったサーバーサイドでレンダリングされるアプリを除外するものではありません。</p>

<p>理屈で説明するよりも、実際に体験した方が早いかと思います。いくつか具体例を挙げましょう。</p>

<ul>
<li><a href="https://www.flipkart.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Flipkart</a></li>
<li><a href="http://www.washingtonpost.com/pwa/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Washington Post</a></li>
<li><a href="https://m.aliexpress.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">AliExpress</a></li>
<li><a href="http://smp.suumo.jp/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">suumo</a></li>
</ul>

<p>※ 他にも様々なプログレッシブウェブアプリが既に存在していますが、<a href="https://pwa.rocks/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">pwa.rocks</a>というサイトにいくつかまとまっていますので、ぜひご覧頂下さい。</p>

<p>実際に使ってみるとわかりますが、これらのアプリケーションにおいてこれまでにない特徴的な点がいくつかあります。</p>

<ul>
<li>ホーム画面に追加してワンタップで起動</li>
<li>キャッシュを使ってオフライン、もしくは高速に動作</li>
<li>プッシュ通知を送信</li>
<li>自動でログイン</li>
</ul>

<h2>プログレッシブとは何か</h2>

<p>「プログレッシブ」という言葉自体は直訳すると「進歩的な」といった意味がありますが、ピンとこない方は多いと思います。</p>

<p>プログレッシブウェブアプリの「プログレッシブ」のひとつの意味は、ウェブページとして使い始めたサービスが、ホーム画面に追加し、オフラインで動作し、プッシュ通知を送り始めるといった流れの中で、「徐々にアプリへと変化していく」様を指しています。</p>

<p>もう一つ意味があります。</p>

<p>フロントエンドエンジニアであれば、プログレッシブ・エンハンスメントという言葉を聞いたことがあると思います。プログレッシブ・エンハンスメントとは、HTML5 時代に続々と新しい機能が登場する中で、最新の標準技術をまだ盛り込んでいないブラウザでも、情報を届けるといった目的をゴールに、必要最低限の機能をベースとして、可能であれば最新技術を使うことでよりリッチな体験を提供する、という設計コンセプトのことを言いました。(逆に、リッチな体験を提供できるブラウザをベースに、最新の技術が使えないブラウザでも最低限の目的は達成できるように設計する手法をグレースフル・デグラデーションと呼びました)</p>

<p>プログレッシブウェブアプリも同様に捉えることができます。つまり、必要最低限の機能を提供できる状態をベースとし、オフラインやプッシュ通知などをプログレッシブな (進歩的な) 機能として提供する、というものです。</p>

<p>これは言い方を変えれば、対応していないブラウザがあるからといって対応を待つべきではなく、それを前提としてウェブを前に進めていこう、というメッセージでもあるのです。実際、プログレッシブウェブアプリ対応への副作用として、複数の機能に未対応のブラウザでも<a href="https://developers.google.com/web/showcase/2016/aliexpress" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">コンバージョンレートが改善したという事例</a>も出ています。</p>

<h2>アプリとウェブのギャップ</h2>

<p>Web2.0の時代を経てコンピューターの世界はネイティブアプリケーションからウェブアプリケーションの時代へと変化を遂げました。地図アプリケーションを思い出して下さい。その昔CD-ROMからせっせとインストールする必要のあった地図が、URLひとつでブラウザから見られるようになったのです。他にも例を挙げればキリがありません。</p>

<p>ウェブはその後もHTML5やその周辺技術の発展により大きく進化していきました。しかしその恩恵を満足の行く形で受けられたのはデスクトップでの話。モバイル・スマートフォンの時代となり、ユースケースが変化していく中で、スマートフォン上で快適に目的を達成するためには、ウェブブラウザは力不足と言われるようになってしまいました。その象徴的な出来事の一つがFacebookのCEOマーク・ザッカーバーグによるこの発言でした。</p>

<p><a href="http://jp.techcrunch.com/2012/09/14/20120911mark-zuckerberg-our-biggest-mistake-with-mobile-was-betting-too-much-on-html5/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Disrupt：ザッカーバーグ、「HTML5を過大評価したのは、われわれ最大の失敗」と認める | TechCrunch Japan</a></p>

<p>これはひとえに標準化を必要とするウェブという環境の特性ゆえと言わざるを得ません。標準化を進めつつ実装し、浸透を待たなければならなかったウェブと異なり、ネイティブアプリはモバイルに最適化した仕様や機能を次々と取り込み、技術革新を起こしていきました。</p>

<p>しかしウェブには、ネイティブアプリでは実現できない特性も持ち合わせています。それが<strong>SLICE</strong>と呼ばれるものです。</p>

<ul>
<li>Secure (安全)</li>
<li>Linkable (リンク可能)</li>
<li>Indexable (インデックス可能)</li>
<li>Composable (再構成可能)</li>
<li>Ephemeral (一時的な利用)</li>
</ul>

<p>ウェブもネイティブも、お互いの短所を埋める進化を遂げていく中で、ウェブが着実に前進していることの現れが、プログレッシブウェブアプリと言えるでしょう。一度はHTML5化を断念したFacebookがプッシュ通知を採用したのはその最たる例です。</p>

<p><a href="http://jp.techcrunch.com/2015/09/15/20150914facechrome/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Facebook、Googleと協力してモバイルウェブユーザーにプッシュ通知を送信</a></p>

<p>プログレッシブウェブアプリはWeb 2.0、HTML5と続いてきた大きな流れの、次の一歩と捉えて間違いありません。</p>

<h2>プログレッシブウェブアプリを構成する機能</h2>

<p>プログレッシブウェブアプリはそれ自体が機能を表しているわけではなく、様々な先進的機能をまとめたひとつのムーブメントです。具体的にどんな機能があるのか、ひとつひとつ見ていきましょう。</p>

<ul>
<li><a href="#pw-https" data-wpel-link="internal">HTTPS</a></li>
<li><a href="#pw-manifest" data-wpel-link="internal">Web App Manifest</a></li>
<li><a href="#pw-sw" data-wpel-link="internal">Service Worker</a></li>
<li><a href="#pw-cache" data-wpel-link="internal">Cache API</a></li>
<li><a href="#pw-push" data-wpel-link="internal">Web Push / Push Notifications</a></li>
<li><a href="#pw-bg" data-wpel-link="internal">Background Sync</a></li>
<li><a href="#pw-budget" data-wpel-link="internal">Web Budget API</a></li>
<li><a href="#pw-credential" data-wpel-link="internal">Credential Management API</a></li>
<li><a href="#pw-payment" data-wpel-link="internal">Payment Request API</a></li>
</ul>

<h3 id="pw-https">HTTPS</h3>

<p>プログレッシブウェブアプリに対応する上で大前提になるのがサイトの完全なHTTPS対応です。ログイン画面や商品購入画面だけではなく、すべてのページをHTTPS化する必要があります。</p>

<p>一般的に、HTTPSに対応することでウェブサイトは</p>

<ul>
<li>ウェブサイトの一意性を守るアイデンティティ(Identity)</li>
<li>サーバー・ブラウザ間の通信を秘匿するコンフィデンシャリティ(Confidentiality)</li>
<li>送受信されるデータを改ざんさせないインテグリティ(Integrity)</li>
</ul>

<p>の3つを手に入れることができます。</p>

<p>プログレッシブウェブアプリ対応において重要なのが、以下でご紹介する機能のほとんどがHTTPS上でのみ動作 (<a href="https://www.w3.org/TR/secure-contexts/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">セキュアコンテキスト</a>)するという点です。こういった機能はPowerful Features と呼ばれ、以前はHTTP上でも動作したgetUserMediaやgeolocationといったAPIもそこに加えられ、最近HTTPSのみで動作する変更が加えられました。</p>

<p>HTTPSに対応することなしにプログレッシブウェブアプリを実現することは不可能ですので、対応を検討する方はここからスタートして下さい。(ちなみにChromeでは、localhostとfile://もセキュアコンテキストに含まれますので、開発時は少し役に立つかもしれません)</p>

<div class="youtube">

<!-- iframe plugin v.4.3 wordpress.org/plugins/iframe/ -->
<iframe src="https://www.youtube.com/embed/YMfW1bfyGSY" frameborder="0" 0="allowfullscreen" width="100%" height="500" scrolling="yes" class="iframe-class"></iframe>

</div>

<h3 id="pw-manifest">Web App Manifest</h3>

<p>ネイティブアプリとウェブサイトを比較した時に、最も大きく異なるのがアクセスのしやすさです。もちろん、アプリのようにインストールしなくても、リンクを踏むだけでアクセスできるという意味で、ウェブは手に届きやすい存在です。しかしスマートフォンの場合、デスクトップのようにキーボードで手軽に検索ができるわけではありません。ホーム画面からタップひとつで起動できるだけで、ユーザーにとっての身近さは大きく改善します。</p>

<p><img src="/wp-content/uploads/2016/09/Screenshot_20160901-153533-169x300.png" alt="screenshot_20160901-153533" style="width: 169px; height: 300px;" class="aligncenter size-medium wp-image-20903" /></p>

<p>そこで登場するのがWeb App Manifestです。Web App Manifestを使うことで、該当ページに関する様々な情報を定義することができます。</p>

<p><a href="https://developer.mozilla.org/ja/docs/Web/Manifest" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Web App Manifest | MDN</a></p>

<p>最近は<code>lang</code>や<code>scope</code>、<code>screenshots</code>といった項目も新しく追加されていますので、その辺りも注目して下さい。</p>

<p>これらの情報を踏まえ、「ホーム画面に追加」をすると、ウェブアプリはホーム画面に鎮座することができるようになります。しかし、この機能がiOSでも古くからある<code>meta</code>タグを使ったものに近いと思われた方もいるかもしれません。</p>

<p>Chromeの場合、このWeb App Manifestといくつかの条件が加わることで、ブラウザが自動的にホーム画面に追加を促してくれる、という点が大きく異なります。詳しくは下記の記事を参照して下さい。</p>

<p><a href="http://qiita.com/horo/items/ff665e4a6613e7684f8f" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Web App ManifestでWebアプリをインストール可能に &#8211; Qiita</a></p>

<h3 id="pw-sw">Service Worker</h3>

<p>Service Workerはプログレッシブウェブアプリを構成する機能の中でも、コンセプトを成立させた一番の立役者で、中核を成すものです。</p>

<p>従来のウェブにおいて、ページはサーバーから送られたHTMLとそれに付随するリソースで構成される機能がすべてであり、ページが閉じられると同時に忘れ去られる存在でした。Service Workerは、ページとは独立して動作するスクリプトを、ページを閉じた後でもブラウザ上で動かし続けることができる機能です。このService Workerを活用することで、様々な可能性が開かれます。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2016/08/serviceworker.png" data-wpel-link="internal"><img src="/wp-content/uploads/2016/08/serviceworker-640x99.png" alt="serviceworker" width="640" height="99" class="alignnone size-large wp-image-20543" srcset="/wp-content/uploads/2016/08/serviceworker.png 640w, /wp-content/uploads/2016/08/serviceworker-300x46.png 300w, /wp-content/uploads/2016/08/serviceworker-207x32.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<p><strong>オフライン</strong>：Service Workerはページが送信するあらゆるリクエストを横取りすることができます。実質的なローカルプロキシーとなるため、強力なキャッシュを活用すれば、ネットワークに接続していない状態でもレスポンスを返すことができるようになります。詳しくはCache APIの項で説明します。</p>

<p><strong>プッシュ通知</strong>：Service Workerはページが閉じた状態でも、また、ブラウザによっては起動してない状態であっても、イベントを検知することができます。そのため、外部サーバーが送信したプッシュリクエストをイベントとして受け取り、何かしらのアクションを起こすことができるのです。詳しくはWeb Push / Web Notificationsの項で説明します。</p>

<p>それでは、Service Workerの使い方を雰囲気だけ見てみましょう。</p>

<p>Service Workerは独立したJavaScriptとして動作するため、ファイルも分けて記述する必要があります。例えばページ上で動作するスクリプト<code>app.js</code>が、<code>service-worker.js</code>というService Workerを使いたいとします。</p>

<p></p><pre class="crayon-plain-tag">navigator.serviceWorker.register('service-worker.js', {scope: './'});</pre><p></p>

<p>これだけでService Workerが登録されます。簡単ですね。</p>

<p><code>service-worker.js</code>の中身はイベント・ドリブンのスクリプトになります。例えば下記のように記述しておけば、あらゆるリクエストをService Workerが拾い上げて、サーバーにリクエストを転送することなく&#8221;Hello World!&#8221;とレスポンスを返します。</p>

<p></p><pre class="crayon-plain-tag">self.addEventListener('fetch', function(event) {  
  event.respondWith('Hello World!');  
});</pre><p></p>

<p>Service Workerは実際いつ動作を開始するのでしょう？影響範囲はどこまででしょう？こういった細かい話になるとセキュリティへの懸念も出てくるため、若干複雑な内容を理解する必要が出てきます。scopeとライフサイクルについては抑えておきましょう。</p>

<h4>scope</h4>

<p>Service Workerが登録されると、以後半永久的にスクリプトを動かし続けることになります。仮にService Workerがドメインの範囲内すべてに影響をおよぼすことができるとすると、ブログなどのユーザーの権限がパスで区切られたサービスでは、自分の預かり知らないスクリプトが埋め込まれてしまう可能性がでてきます。そこでService Workerでは、scopeという概念を使って影響範囲を制限します。詳しくはこちらの記事が参考になります。</p>

<p><a href="http://qiita.com/nhiroki/items/eb16b802101153352bba" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ServiceWorkerのスコープとページコントロールについて &#8211; Qiita</a></p>

<h4>ライフサイクル</h4>

<p>Service Workerが登録されたあと、スクリプトを手動で更新したい場合もあります。新しいスクリプトはすぐに有効になるのでしょうか？その場合古いスクリプトはどうなってしまうのでしょうか？Service Workerは放っておいたら永久に更新されないのでしょうか？</p>

<p>Service Workerのライフサイクルを正しく理解することはとても重要です。下記の記事をぜひご覧ください。</p>

<ul>
<li><a href="http://www.html5rocks.com/ja/tutorials/service-worker/introduction/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Service Workerの紹介: Service Workerの使い方 &#8211; HTML5 Rocks</a> (一部古い内容が含まれます)  </li>
<li><a href="https://blog.jxck.io/entries/2016-04-24/service-worker-tutorial.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">中級者向け Service Worker Tutorial | blog.jxck.io</a>  </li>
<li><a href="http://blog.nhiroki.jp/2015/07/05/service-worker-registration" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Service WorkerのRegistration</a>  </li>
</ul>

<h4>デバッグ</h4>

<p>Chromeではプログレッシブウェブアプリのデバッグをしやすくするために、最近DevToolsにResourcesパネルの代わりに Applicationパネルが追加されました。Manifestや各種ストレージなどを、ひとつのパネルからまとめて確認することができます。中でもService Worker専用の項目では、現在起動中のスクリプトだけでなく</p>

<ul>
<li>Offline &#8211; オフラインのエミュレーションボタン</li>
<li>Update on reload &#8211; リロードするだけでService Workerを更新</li>
<li>Bypass for network &#8211; ネットワークリクエストの横取りを一時的に停止</li>
</ul>

<p>といったオプションが利用できます。ここからService Workerの単独のDevToolsを開いてデバッグを行ってください。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2016/08/devtools.png" data-wpel-link="internal"><img src="/wp-content/uploads/2016/08/devtools-640x238.png" alt="devtools" width="640" height="238" class="alignnone size-large wp-image-20542" srcset="/wp-content/uploads/2016/08/devtools.png 640w, /wp-content/uploads/2016/08/devtools-300x112.png 300w, /wp-content/uploads/2016/08/devtools-207x77.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<h4>少し未来の話</h4>

<p>今後利用可能になるService Worker周辺の重要な機能についても少し触れておきましょう。</p>

<p><strong>Link rel=serviceworker</strong>
Chrome 54からOrigin Trial (特定のドメインに実験的にホワイトリストで機能を提供) ベースでService Workerの登録が linkタグやHTTPヘッダーで行えるようになりました。将来的にこれが利用できるようになれば、JavaScriptを記述することなく、linkタグやHTTPヘッダーのみでService Workerを登録できるようになります。</p>

<p></p><pre class="crayon-plain-tag">&lt;link rel="serviceworker" href="/js/sw.js" scope="/"&gt;</pre><p></p>

<p><a href="https://www.chromestatus.com/feature/5682681044008960" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">https://www.chromestatus.com/feature/5682681044008960</a></p>

<p><strong>Foreign fetch</strong>
また、Web Fontsのような複数ドメインから共有されるリソースをCDN経由で提供するサーバーのリソースも、現在は利用する側のService Workerがハンドリングすることが可能ですが、これをCDN側のService Workerがハンドリングできれば効率が向上します。これを可能にする機能はForeign Fetchと呼ばれ、Chrome 54からOrigin Trialベースで提供が開始されています。</p>

<p><a href="https://www.chromestatus.com/feature/5684130679357440" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">https://www.chromestatus.com/feature/5684130679357440</a></p>

<p>その他、Service Workerのさらに詳しい情報はHTML5 Conference 2016で行われたChromeエンジニアの保呂さんのスライドが参考になります。<br />
<a href="https://goo.gl/YxL2L7" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Service Worker Deep Dive</a></p>

<h3 id="pw-cache">Cache API</h3>

<p>先程説明したように、Service Workerを使ってあらゆるリクエストを横取りすることで、オフラインの機能が実現可能になります。そこで強力なキャッシュ機能を提供するのがCache APIです。</p>

<p>Cache APIは取得されたリソースだけでなく、リクエストやレスポンスの内容も含めて保存されます。下記の例では、キャッシュが残っていればキャッシュされていたレスポンスを、なければサーバーにリクエストを送って、返ってきたレスポンスを返します (キャッシュに保存はしません)。</p>

<p></p><pre class="crayon-plain-tag">self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request).then(function(response) {
      return response || fetch(event.request);
    })
  );
});</pre><p></p>

<p>Cache APIを使った実例について、詳しくはこちらの記事が参考になります。</p>

<p><a href="http://qiita.com/horo/items/175c8fd7513138308930" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ServiceWorkerとCache APIを使ってオフラインでも動くWebアプリを作る &#8211; Qiita</a></p>

<p>なお、Cache APIを扱う上で fetch()も避けては通れませんが、ググらビリティの低さから、まとまった資料が見つかりにくいという問題があります。こちらのページがよくまっていたのでリンクしておきます。</p>

<p><a href="http://qiita.com/tomoyukilabs/items/9b464c53450acc0b9574" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">お疲れさまXMLHttpRequest、こんにちはfetch &#8211; Qiita</a></p>

<p>ここまで述べてきたように便利なService Worker + Cache APIですが、多くの人が似たようなコードを書くであろうことは容易に想像ができます。そこで便利なライブラリがいくつかあります。</p>

<h4>sw-toolbox</h4>

<p>リソースをキャッシュする際に必要になるのが、リソースの優先順位の判定です。例えば共通で利用されるJavaScriptファイルは、更新がない限りネットワークにリクエストを送るまでもなく常にキャッシュから読み込むことでスピードを優先したいと思うはずです。逆に例えば、天気アプリであれば、開く度に最新の天気予報を見たいですが、オフラインだった場合はオフラインだと言われるよりは、キャッシュからでもその後の天気予報を見たいと思うはずです。</p>

<p>このように、同じキャッシュを活用するでも、場面によってキャッシュを優先したいのか、ネットワークを優先したいのかが異なってきます。そこで便利なのが<a href="https://github.com/GoogleChrome/sw-toolbox" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">sw-toolbox</a>です。</p>

<p></p><pre class="crayon-plain-tag">toolbox.router.get('/myapp/index.html', toolbox.networkFirst);</pre><p></p>

<p><a href="https://html5experts.jp/wp-content/uploads/2016/08/appshell.png" data-wpel-link="internal"><img src="/wp-content/uploads/2016/08/appshell-640x258.png" alt="appshell" width="640" height="258" class="alignnone size-large wp-image-20539" srcset="/wp-content/uploads/2016/08/appshell.png 640w, /wp-content/uploads/2016/08/appshell-300x121.png 300w, /wp-content/uploads/2016/08/appshell-207x83.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<p>sw-toolboxではネットワークを優先するnetworkFirst、キャッシュを優先するcacheFirstの他にもfastest、networkOnly、cacheOnlyといった様々なオプションが利用可能です。</p>

<p><a href="https://googlechrome.github.io/sw-toolbox/docs/master/index.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">https://googlechrome.github.io/sw-toolbox/docs/master/index.html</a></p>

<h4>sw-precache</h4>

<p>Service Workerを使ったキャッシュ機能以前にオフラインを実現する機能として登場した<a href="https://developer.mozilla.org/ja/docs/Web/HTML/Using_the_application_cache" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Application Cache</a>は、ページを初めて開いた時点で、予め定義されたリソースをすべてキャッシュするものでした。Service Worker + Cache APIにおいても同様のニーズはあるでしょう。例えばアプリの外枠や必要最低限のCSSやJavaScriptファイルを予めロードしておくことで、コンテンツ部分のみをダイナミックにロードすればよいという<a href="https://github.com/GoogleChrome/application-shell" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Application Shell</a>というアーキテクチャを利用する場合です。</p>

<p>これを実現するのに便利なライブラリが<a href="https://github.com/GoogleChrome/sw-precache" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">sw-precache</a>です。Gulp やGruntといったタスクランナーを使うことで、リストされたリソースを最初のロード時点でキャッシュしてしまうJavaScript のコードを出力してくれます。あとはこれをService Workerとしてロードすればよいだけです。また、リソースの更新もハッシュを使って自動的に管理してくれるので、どのファイルを書き換えたからリストを変更しなければならない、といったようなマニュアル作業が不要になります。</p>

<p></p><pre class="crayon-plain-tag">gulp.task('generate-service-worker', function(callback) {
  var path = require('path');
  var swPrecache = require('sw-precache');
  var rootDir = 'app';

  swPrecache.write(path.join(rootDir, 'service-worker.js'), {
    staticFileGlobs: [rootDir + '/**/*.{js,html,css,png,jpg,gif,svg,eot,ttf,woff}'],
    stripPrefix: rootDir
  }, callback);
});</pre><p></p>

<p>なお、最近追加されたruntimeCachingという機能を使うことで、<a href="https://github.com/GoogleChrome/sw-precache#runtimecaching-arrayobject" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">sw-toolbox の便利な機能を宣言的に記述</a>することもできます。</p>

<h4>sw-appcache-behavior</h4>

<p>もし既にApplication Cacheを使っていて、Service Workerに移行を検討している場合は、<a href="https://github.com/GoogleChrome/sw-helpers" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">sw-helpers</a>ライブラリの一部である<a href="https://github.com/GoogleChrome/sw-helpers/tree/master/projects/sw-appcache-behavior" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">sw-appcache-behavior</a>が便利です。既存の Manifestファイルをそのまま利用してService Workerによるオフラインを実現することができます。</p>

<h4>sw-offline-google-analytics</h4>

<p>オフラインのウェブサイトがうまく作れたとしても、ユーザーがどのアクセスページにアクセスし、どのように利用しているかが分からなければ、本当に役に立っているのかどうかを知ることはできません。これもsw-helpersの一部である<a href="https://developers.google.com/web/updates/2016/07/offline-google-analytics?hl=en" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">sw-offline-google-analytics</a>を使えば、オフライン中のアクセス解析をデータベース上に保存しておいて、オンラインになったタイミングでサーバーに送信してGoogle Analyticsでアクセス解析結果を閲覧することができるようになります。</p>

<h3 id="pw-push">Web Push / Web Notifications</h3>

<p>プッシュ通知は、プログレッシブウェブアプリを語る際、これまでできなかったことの中で、技術者ではなくても効果が理解できるという意味では、最も分かりやすい機能です。実際に既に多くのサービスがこれを利用しています。例えば Facebook です。<a href="http://m.facebook.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">モバイルウェブ版のFacebook</a>にアクセスしてみると、すぐにそのことに気付くでしょう。</p>

<p></p><pre class="crayon-plain-tag">navigator.serviceWorker.ready().then(function(sw) {
  sw.pushManager.subscribe({userVisibleOnly: true})
    .then(function(sub) {
      // パーミッション取得後
      sendSubToServer(sub);  // Send subscription to the server
  });
});</pre><p></p>

<p><a href="https://html5experts.jp/wp-content/uploads/2016/08/push1.png" data-wpel-link="internal"><img src="/wp-content/uploads/2016/08/push1-640x130.png" alt="push1" width="640" height="130" class="alignnone size-large wp-image-20540" srcset="/wp-content/uploads/2016/08/push1.png 640w, /wp-content/uploads/2016/08/push1-300x61.png 300w, /wp-content/uploads/2016/08/push1-207x42.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<p></p><pre class="crayon-plain-tag">self.addEventListener('push', function(event) {
  event.waitUntil(
    self.registration.showNotification(title, {
      body: body, icon: icon, tag: tag,
      actions: [{action: 'remindMe', title: 'REMIND ME'}]
    }
  });
});</pre><p></p>

<p><a href="https://html5experts.jp/wp-content/uploads/2016/08/push2.png" data-wpel-link="internal"><img src="/wp-content/uploads/2016/08/push2-640x122.png" alt="push2" width="640" height="122" class="alignnone size-large wp-image-20541" srcset="/wp-content/uploads/2016/08/push2.png 640w, /wp-content/uploads/2016/08/push2-300x57.png 300w, /wp-content/uploads/2016/08/push2-207x39.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<p>具体的な実装方法は若干複雑ですので、サードパーティーのサービスを使うのも手かもしれません。自分で実装する場合は、こちらのドキュメントがよくまとまっています。</p>

<p><a href="http://qiita.com/tomoyukilabs/items/217915676603fda73b0a" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Web Pushでブラウザにプッシュ通知を送ってみる &#8211; Qiita</a><br />
<a href="http://qiita.com/tomoyukilabs/items/c7268aa29447a1d0a3fb" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Firefox (Developer Edition)でW3C Push APIを使ってみる &#8211; Qiita</a></p>

<p>Chromeの場合、以前はGCM (Google Cloud Messaging、もしくはFirebase Cloud Messaging)が必須でしたが、現在は<a href="https://tools.ietf.org/html/draft-ietf-webpush-protocol-08" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">標準の Web Push</a>が利用できます。詳しくは下記をご覧下さい。</p>

<p><a href="http://qiita.com/tomoyukilabs/items/8fffb4280c1914b6aa3d" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ChromeでW3C Push APIを使ってみた &#8211; Qiita</a></p>

<p>Web Pushについては、<a href="https://github.com/web-push-libs/web-push" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">node.js 向けのライブラリ</a>も提供されています。</p>

<h3 id="pw-bg">Background Sync</h3>

<p>妙なタイミングでネットワークがオフラインになってしまったために、リクエストが送れなかったという経験は誰しもあると思います。そんな時にリクエストをキューしておいて、オンラインになったタイミングで送ってくれるとありがたいですよね。それを実現してくれるのが、Background Syncです。</p>

<p><a href="http://qiita.com/horo/items/28bc624b8a26ffa09621" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ServiceWorkerのBackground Syncでオンライン復帰時にデータ送信 &#8211; Qiita</a></p>

<h3 id="pw-budget">Web Budget API</h3>

<p>現状Service Workerはプッシュを受信すると、通知を出さなければなりません。これはブラウザリソースの無駄遣いを防ぐためです。しかし、例えばバックグラウンドで購読しているフィードを更新するといったユースケースは容易に思いつきます。</p>

<p>そこで検討されているのが<a href="https://beverloo.github.io/budget-api/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Web Budget API</a>という機能です。これを使うことで、ページは与えられたバジェットを適切に配分してバックグラウンドでの処理を行うことが可能になりますので、リソースの無駄遣いを防ぎつつ必要な機能を実現できるようになるはずです。</p>

<p><a href="https://www.chromestatus.com/features/5691190548627456" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">https://www.chromestatus.com/features/5691190548627456</a></p>

<h3 id="pw-credential">Credential Management API</h3>

<p>Credential Management APIはユーザーのクレデンシャル (認証情報) を制御するためのAPIです。</p>

<div class="youtube">

<!-- iframe plugin v.4.3 wordpress.org/plugins/iframe/ -->
<iframe src="https://www.youtube.com/embed/O3mBdKYMsMY" frameborder="0" 0="allowfullscreen" width="100%" height="500" scrolling="yes" class="iframe-class"></iframe>

</div>

<p>これを使うことにより</p>

<ul>
<li>id / passwordをブラウザに覚えさせる</li>
<li>ソーシャルログインの選択肢をブラウザに覚えさせる</li>
<li>ログイン時にアカウント選択ダイアログを提供する</li>
<li>ユーザーを自動的にログインさせる</li>
</ul>

<p>といったことが可能になります。</p>

<p>典型的なユースケースとしては、ニュースサイトやコマースサイトといった、必ずしもログインしなくてもよい、しかし提供者側としてはログインしてもらいたいサービスにおいて役立ちます。実際に利用されている例としては<a href="https://m.aliexpress.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">AliExpress</a>の実装が非常によくできていますので、是非一度お試し下さい。</p>

<p>実装は基本的にフロントエンド側だけですので、比較的気軽に導入することができます。</p>

<ul>
<li><a href="https://credential-management-sample.appspot.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">デモアプリ</a> (<a href="https://github.com/GoogleChrome/credential-management-sample" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ソースコード</a>)</li>
<li><a href="https://developers.google.com/web/updates/2016/04/credential-management-api" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">翻訳済みのドキュメント</a></li>
<li><a href="http://g.co/codelabs/cmapi" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">実際に実装を体験できるコードラボ</a></li>
<li><a href="http://w3c.github.io/webappsec-credential-management/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">仕様</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Credential_Management_API" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">MDN リファレンス</a></li>
</ul>

<h3 id="pw-payment">Payment Request API</h3>

<p>Payment Request APIは支払い時のチェックアウトに必要なフォームを置き換えるUIを提供します。Chromeではバージョン 53から利用できるようになる予定です。</p>

<div class="youtube">

<!-- iframe plugin v.4.3 wordpress.org/plugins/iframe/ -->
<iframe src="https://www.youtube.com/embed/hmqZxP6iTpo" frameborder="0" 0="allowfullscreen" width="100%" height="500" scrolling="yes" class="iframe-class"></iframe>

</div>

<p>Payment Request APIが提供するのは、ユーザーインターフェースです。ブラウザのAutofill機能を活用することで、クレジットカードの情報や住所などを、すばやく簡単に入力できるようになります。</p>

<p>支払い方法は現状クレジットカードのみですが、まもなくAndroid Payも利用可能 (残念ながら当初日本は対象外) になる予定です。将来的には、さらに様々な支払い方法をオープンかつ柔軟に組み込めるようになっていく予定です。</p>

<ul>
<li><a href="https://developers.google.com/web/updates/2016/07/payment-request" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">アナウンス・概要</a></li>
<li><a href="https://developers.google.com/web/fundamentals/primers/payment-request/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">実装ガイド</a></li>
<li><a href="https://developers.google.com/web/fundamentals/primers/payment-request/android-pay" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Android Pay 実装ガイド</a></li>
<li><a href="https://www.w3.org/TR/payment-request/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">仕様</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Payment_Request_API" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">MDN リファレンス</a></li>
</ul>

<h3>その他の機能</h3>

<p>プログレッシブウェブアプリを語る上で数えるべき機能や考え方は他にもいくつかありますが、キリがありませんのでこの辺にしておきましょう。</p>

<ul>
<li>Web Bluetooth</li>
<li>Web MIDI</li>
<li>Web Animation</li>
</ul>

<p>興味のある方は、この辺りもぜひ抑えておいていただければと思います。</p>

<h2>Lighthouse</h2>

<p>あるウェブアプリを指してそれがプログレッシブウェブアプリかどうかを議論するのはあまり意味のないことですが、それを示す指標を得ることはできます。それが<a href="https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Lighthouse</a>というChrome拡張機能です。ウェブサイトを開いた状態でこの拡張を起動すると、プログレッシブウェブアプリの対応度合いをスコアで示してくれます。</p>

<p><img src="https://lh3.googleusercontent.com/69AN0502kzahk9AmzmLGzRvsVy_6zq2gUnPB8ZH2NIVKMF8DSf9qw44bIh2v9CDVy1FQHFMq1r1US9dey9mjUjA7jg_lLnLcXseLHMVGDDyjGVGetdVCJFu4YlZmQPW18jAcgdg-" alt="" /></p>

<p>Chrome拡張機能としてだけではなく、node moduleとしても利用が可能です。</p>

<p><a href="https://github.com/GoogleChrome/lighthouse" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">https://github.com/GoogleChrome/lighthouse</a></p>

<p>Lighthouseはまだアルファ版の段階のため、評価できない機能が多数ありますが、今後対応していく予定です。</p>

<h2>リソース</h2>

<p>プログレッシブウェブアプリに興味を持たれた方で、最新情報を追いかけたいという方は下記のページをご覧下さい。RSSフィードも配信しています。</p>

<p><a href="https://developers.google.com/web/updates/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">https://developers.google.com/web/updates/</a></p>

<p>資料が英語で読めない？英語が分かる人はぜひ、<a href="http://qiita.com/yoichiro6642/items/3afc2f01706398a5a458" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">翻訳にご協力下さい</a>。</p>

<h2>最後に</h2>

<p>プログレッシブウェブアプリについて長々と書いてきましたが、重要なのは決してこれらの機能すべてに対応することではありません。自分が提供するサービスがユーザーに最大の価値を提供するために必要であれば、ネイティブアプリを提供するべき場合もあるでしょう。オフライン機能だけが必要な場合もあるかもしれません。これらの機能をうまく組み合わせて、ユーザーが本当に求めている価値を提供できるアプリを開発していただければと思います。</p>
]]></content:encoded>
		
		<series:name><![CDATA[Web技術でアプリ開発2016]]></series:name>
	</item>
	</channel>
</rss>
