<?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="/uskay/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>「改めまして、Progressive Web Appsと申します」── Web UXの新たな基準を考える</title>
		<link>https://html5experts.jp/uskay/25391/</link>
		<pubDate>Thu, 19 Apr 2018 03:23:45 +0000</pubDate>
		<dc:creator><![CDATA[宇都宮佑亮]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[PWA]]></category>
		<category><![CDATA[Progressive Web Apps]]></category>
		<category><![CDATA[Service Worker]]></category>
		<category><![CDATA[UX]]></category>
		<category><![CDATA[Webアプリ]]></category>

		<guid isPermaLink="false">/?p=25391</guid>
		<description><![CDATA[Progressive Web Appsというワードが世に出て約2年半が経ちました。2015年10月に開催されたChrome Dev SummitにてFlipkartの事例をもってお披露目となったそのコンセプトは、201...]]></description>
				<content:encoded><![CDATA[<p><strong>Progressive Web Appsというワードが世に出て約2年半が経ちました。</strong>2015年10月に開催されたChrome Dev Summitにて<a href="https://www.youtube.com/watch?v=StdKz32M1RM" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Flipkartの事例</a>をもってお披露目となったそのコンセプトは、2018年現在までに徐々に成功事例を増やしながらWeb界隈の注目を集め、ついに先日（忘れもしない2018年3月30日！）iOS 11.3からiOSデバイスでも一部の機能が利用できるようになるまで成長しました。これは、まるで進学する我が子を見ているかのような、新年度にふさわしい晴れやかなニュースですし、<strong>いい機会なので PWAとは何かを改めて振り返ってみようと思います。</strong></p>

<p><img src="/wp-content/uploads/2018/04/pwa01.jpg" alt="pwa01" /></p>

<h2>Webに足りなかったもの</h2>

<p>私はWebが大好きです。リンクを1つクリックしたら（インストールなど煩わしい手続きなしで）すぐに新しいコンテンツを読めるのは最高の体験だなと常日頃感じています。ただし、<strong>今までのWebアプリのユーザー体験は決して最適なものではないとも思っています。</strong>たとえば以下のような体験をした覚えはありませんか？</p>

<ul>
<li>朝の満員電車でも情報収集に勤しむ現代のビジネスパーソンのあなた。つり革に捕まりながらなんらかの記事コンテンツを見ようとリンクをタップする</li>
<li>途端にHTMLのレスポンス待ちで真っ白な画面。レスポンスが返ってきたと思ったら今度はWebアプリ側のローディングGIFが動き出す。</li>
<li>しばらく待つとテキストが表示され読み始めるものの、時間差で画像が差し込まれレイアウトがずれる（どこを読んでいたんだっけ？）。極めつけは全画面広告が画面を占拠し、嫌になってそっとブラウザを閉じる（代わりにソーシャルアプリやゲームアプリを起動する）。</li>
</ul>

<p>このように世に出回っている多くのWebアプリはパフォーマンスに課題があります。特に、さまざまなスペックなデバイスがあらゆる環境で利用されるモバイルにおいては、Webアプリは単純に耐えられないくらい遅く、実測で3G回線と同等な環境における平均ページロード時間は19秒もかかっているという統計もあります[1]。 <strong>Webアプリはとにかくこのパフォーマンスをどうにかしなければなりません。</strong></p>

<p>一方ですでにネイティブ アプリに慣れ親しんでいるユーザーの期待値を満たすためには、パフォーマンスを改善するだけでは十分ではありません。</p>

<ul>
<li>ホーム画面にアイコンを追加したり</li>
<li>プッシュ通知がタイミングよく送られてきたり</li>
<li>オフラインでも動作する信頼性だったり</li>
</ul>

<p>「ユーザー体験の基準」がどんどん上がっていくなか、Webアプリだけがこのような体験を提供できずに取り残されている状況がずっと続いていました。<strong>時代に合わせて、ユーザーが求める機能性もWebアプリで実現できなければならないのです。</strong></p>

<h2>PWAはベストプラクティス集である</h2>

<p>そこで満を持して登場したのがPWAです。PWAと聞くと何かを特定の技術を指すものと思われるかもしれませんが、実はそのコンセプトは幅広く、どちらかというと前述した <strong>Webアプリ本来の課題を解決し、よりよいユーザー体験を実現するためのベストプラクティス集のようなものです。</strong>Googleが提供している<a href="https://developers.google.com/web/progressive-web-apps/checklist" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Progressive Web App Checklist</a>
なるものがあり詳細な内容はそちらを確認いただければと思いますが、PWAのコンセプトをざっくり申し上げると以下となります。</p>

<ul>
<li><strong>とにかくパフォーマンスいいWebアプリを作りましょう。</strong>SPAでもSPAじゃなくても、どんなフレームワーク使っても使わなくても、なんでもいいので、表示が速くて画面遷移がスムーズなものにしてユーザーに好かれましょう。</li>
<li>また、最新のWeb APIを積極的に使って、機能性も身につけましょう。たとえば、Webアプリをホーム画面に追加できるようにしたり、オフラインでも動作するようにしたり。<strong>そんな今までWebアプリでは実現できなかった機能が実装できるようになったんだから、やらない手はないでしょう？</strong></li>
</ul>

<p>少し上記でも触れていますが、PWAはあくまでベストプラクティス集なので特定のサードパーティーフレームワークやライブラリには依存しません。世の中には ReactやAngularを使ったPWAもありますし、Vanilla JavaScriptなPWAもあります。また、サーバーサイドの構成には一切言及しません。<strong>したがって技術スタックを変えずとも適用可能なベストプラクティスでありますし、一度に全部を適用するのではなく段階的に（= Progressively）最適化することもできます。</strong></p>

<p>以下の項目でPWAの特徴をより具体的に見ていきます。</p>

<h3>ハイパフォーマンス</h3>

<p>何より重要であり最も難しいテーマとなります。パフォーマンスの基準としては、2015年にChromeチームが発表したユーザー中心に考えるパフォーマンスモデルである<strong>RAIL</strong>[2]を前提に考えていただければ間違いありませんが、各Webアプリの特性や環境に応じてそれぞれのサービスごとに <strong>Performance Budget</strong>（ロード時間やファイルサイズ等の上限を決め、それを「予算」として管理する）を設けることをオススメします。たとえば、2017年のChrome Dev SummitでChromeチームが推奨したPerfromance Budgetは、<strong>TTI（Time to interactive)を5秒以内</strong>、それを実現するために<strong>クリティカルパスのファイルサイズを170KB以内に収める</strong>というものです。[3][4]</p>

<p>何事もまずは現状分析から。Webアプリのパフォーマンス測定やプロファイリングをする<a href="https://developers.google.com/web/tools/lighthouse/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Lighthouse</a>や<a href="https://developers.google.com/web/tools/chrome-devtools/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Chrome DevTools</a>等のツールを使って現状の評価とボトルネックを確認し、対応すべきポイントを決めて最適化を進めます。その後は<a href="https://calibreapp.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Calibre</a>や<a href="https://speedcurve.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">SpeedCurve</a>といったパフォーマンスモニタリングツールを利用して定点観測するといいでしょう。</p>

<p><img src="/wp-content/uploads/2018/04/pwa02.png" alt="pwa02" /></p>

<p>ハイパフォーマンスなPWAを作るためのデザインパターンである<a href="https://developers.google.com/web/fundamentals/performance/prpl-pattern/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">PRPLパターン</a>もまた参考にすべき方式です。PRPLパターンは<strong>Push 、Render、Pre-cache、Lazy-load</strong>の頭文字を取ったもので、主に<a href="https://developers.google.com/web/fundamentals/architecture/app-shell?hl=ja" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">App Shell モデル</a>やSPAを採用したWebアプリのために用意されたパターンですが、それ以外の構成に関してもパフォーマンス向上のヒントとなる点が多くあります。</p>

<ul>
<li><strong>Push/Render:</strong> 初期描画に必須なリソースを<a href="https://tools.ietf.org/html/rfc7540#section-8.2" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">HTTP/2 Server Push</a>するか <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">link rel=preload</a> を利用することで先行取得します。そしてそのリソースを利用し、特にAbove the fold [5] (スクロールしないで見える範囲)を優先してレンダリングします。</li>
<li><strong>Pre-cache:</strong> 次ページ（またはルート）で使用するであろうリソースを先読みします。これには<a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Service Worker</a>を利用するといいでしょう。</li>
<li><strong>Lazy-load:</strong> 初期描画に必要なもの以外はすべてLazy-loadします。SPAであれば別ルートの取得がこちら該当しますし、スクロールに合わせたフラグメントの取得であれば<a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Intersection Observer API</a>を利用するといいでしょう。</li>
</ul>

<p>上記のとおり、Webアプリでもパフォーマンスをあげるためのツールやデザインパターンなど、使えるナレッジが多くたまってきました。ぜひともこれらを利用してハイパフォーマンスなWebアプリの開発を実現してください。</p>

<h3>ホーム画面に追加</h3>

<p><a href="https://developer.mozilla.org/en-US/docs/Web/Manifest" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Web App Manifest</a>を実装するとWebアプリをホーム画面に追加できるようになります。以下のようなJSON形式のマニフェストファイルを用意し、</p>

<p></p><pre class="crayon-plain-tag">{
   "name": “PWA Demo Application”,    
   "short_name": “PWA demo”,
    "icons": [{
        "src": “/assets/icon.png”, "sizes": “192x192”
     }],
    "start_url": “/index.html”,
    "display": “standalone”,
    "scope": “/”
}</pre><p></p>

<p>link タグでページにひも付けた上で、Service Workerをインストールすると、</p>

<p></p><pre class="crayon-plain-tag">&lt;link rel="manifest" href="/manifest.json"&gt;

&lt;script&gt;
if ('serviceWorker' in navigator)    
   navigator.serviceWorker.register('/sw.js')
&lt;/script&gt;</pre><p></p>

<p>このようにホーム画面へ追加を促すプロンプトが上がってきます。ホームに追加した後はフルスクリーンで起動しますし、Androidの場合は1つの アプリとしてみなされディープリンクまで可能です。</p>

<p><img src="/wp-content/uploads/2018/04/pwa03.gif" alt="pwa03" /></p>

<p>1点補足すると、この「ホーム画面に追加」は強力ですが、よりユーザーに気持ちよく追加してもらえるように、<strong>意味のあるタイミングでプロンプトを表示するとさらにいいでしょう。</strong>これを実現するためにぜひとも<code>onbeforeinstallprompt</code>イベントハンドラーを利用してください。</p>

<p><code>onbeforeinstallprompt</code>イベントハンドラーはプロンプトが表示される直前に呼び出されます。そのタイミングでプロンプト表示が適切でなければ表示をキャンセルし、別の任意のタイミングで表示することができます。たとえば、画面上に独自の「ホームに追加アイコン」を作成し、それの <code>onclick</code>のイベントハンドラ内でプロンプトを表示させることも可能です。</p>

<p></p><pre class="crayon-plain-tag">var deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) =&gt; {
  console.log('beforeinstallprompt Event fired');
  // デフォルトのタイミングでは表示させない
  e.preventDefault();
  // Eventオブジェクトを保存しておく
  deferredPrompt = e;
  return false;
});
// どっか別のタイミングで...
deferredPrompt.prompt();</pre><p></p>

<p>また執筆時点での最新の<a href="https://www.google.com/chrome/browser/canary.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Chrome Canary</a> (67.0.3394.0)ではプロンプト表示形式を以下のように変更して、ホームに追加の体験をより良くすべく機能検証をしています。ポイントはページ下部に表示されるバナーがコンテンツの邪魔にならないサイズに調整され、PWAが追加済であればそのディープリンク用のバナーに差し替えます。また、前述の<code>prompt</code>関数を利用してユーザーのインタラクションに応じてプロンプトを表示する際は、モーダル表示に切り替わります。</p>

<p><img src="/wp-content/uploads/2018/04/pwa04.png" alt="pwa04" /></p>

<h3>オフライン対応</h3>

<p>ハイパフォーマンスの解説でも少し登場した<strong>Service Worker</strong> と <a href="https://developer.mozilla.org/en-US/docs/Web/API/Cache" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Cache API</a>を利用することでWebアプリをオフラインで実行することが可能になります。Service Workerとはオリジン単位（またはパスの粒度）でインストール可能なJavaScriptで書かれたクライントサイドプロキシのことで、ページ内で発生するHTTPリクエスト / レスポンスを監視したり、それを書き換えたり、必要に応じてリソースを先読みすることもできます。これとCache APIというHTTPリクエスト/ レスポンスオブジェクトをKey-Value形式で保存できるAPIを組み合わせることで、<strong>オフライン時でもあらかじめキャッシュしておいたレスポンスを利用すことができるようになるわけです。</strong></p>

<p><img src="/wp-content/uploads/2018/04/pwa05.png" alt="pwa05" /></p>

<p>このService WorkerとCache APIの組み合わせは<a href="https://developers.google.com/web/fundamentals/primers/service-workers/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">「Service Worker の紹介」</a>に記載の方法で使用することができますが、より汎用的な使い方をまとめた<a href="https://developers.google.com/web/tools/workbox/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Workbox</a>というライブラリを利用するのも1つの手です。Workbox を利用すると実装が煩雑になる、特定のファイルのラインタイムキャッシュも以下のようにシンプルに記述することができます。</p>

<p></p><pre class="crayon-plain-tag">workbox.routing.registerRoute(
  new RegExp('.*\.js'),
  workbox.strategies.networkFirst()
);</pre><p></p>

<p>Workboxはその他にも、<a href="https://developers.google.com/web/tools/workbox/modules/workbox-precaching" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ファイル単位でリビジョンを付与したPrecaching</a>、<a href="https://developers.google.com/web/tools/workbox/modules/workbox-cache-expiration" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Expirationの定義</a>や<a href="https://developers.google.com/web/tools/workbox/guides/enable-offline-analytics" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Background Syncを利用したオフライン時の Google Analytics の計測</a>などの機能も提供します。</p>

<p>オフラインの戦略はWebアプリの特性に応じて変わってくるものです。例えばニュースサイトであれば、トップページに出ている注目記事をすべて先読みし、オフラインでも読めるようにすることも考えられますし、ECサイトであればまた別の戦略が適している場合もあるでしょう。電波状況が比較的良好な日本においても、速度制限や電車内などオフライン（または不安定なネットワーク）になりえるユースケースは存在しますし、最低限でも <a href="https://www.google.co.jp/search?q=Offline+Dinosaur&amp;source=lnms&amp;tbm=isch&amp;sa=X&amp;ved=0ahUKEwiHmNqQ05vaAhUDOJQKHUkjBh0Q_AUICigB&amp;biw=1745&amp;bih=1003" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Offline Dinasour</a>はユーザーに見せないようにフォールバックページを用意すべきです。</p>

<h3>その他のWeb API</h3>

<p>以下にPWAを実装する上で注目すべきその他のWeb APIを列挙します。</p>

<ul>
<li><strong>プッシュ通知:</strong> <a href="https://developer.mozilla.org/en-US/docs/Web/API/Push_API" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Push API</a> / <a href="https://developer.mozilla.org/en-US/docs/Web/API/notification" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Notification API</a></li>
<li><strong>自動ログイン:</strong> <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">Credential Management API</a></li>
<li><strong>支払いフォームの強化:</strong> <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">Payment Request API</a></li>
</ul>

<p>上記のAPIも組み合わせることによって、リエンゲージメント性の向上や商品の購買フローを最適化することができます。</p>

<h2>クロスプラットフォームなイニシアチブ</h2>

<p>上記にあげたPWAで利用するWeb APIは、すべてのブラウザで利用できることを目標に標準化を進めています。個別の対応状況を確認するには<a href="https://caniuse.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Can I Use</a>をご参照いただければと思いますが、冒頭に述べましたとおりiOSでもiOS 11.3からSafariでService Workerが動作するようになりましたし、Microsoft はWindowsストアにPWAを載せはじめました[6]。このように、さまざまな形でPWAのクロスプラットフォーム利用の機運が高まっていると言えます。</p>

<p>また、PWAは<a href="https://en.wikipedia.org/wiki/Progressive_enhancement" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Progressive Enhancement</a>な実装を推奨している点も改めて触れておきます。たとえばService Workerを利用したオフラインキャッシュの実装は、Service Workerが未実装なブラウザでもWebアプリ本来の動作には影響がないように以下のように条件分岐をいれることを推奨しています。</p>

<p></p><pre class="crayon-plain-tag">// ServiceWorkerが利用できる場合にのみ
if ('serviceWorker' in navigator) {
  // ServiceWorkerを登録する
  navigator.serviceWorker.register('/sw.js')
}</pre><p></p>

<p>特定の環境のみでしか動かないWebアプリを作るのではなく、どの環境でもハイパフォーマンスに動作するようにし、最新のWeb APIが利用できる環境では進んでそれをレバレッジするとよいでしょう。</p>

<h2>Webアプリ vs ネイティブ アプリ</h2>

<p>PWAはその機能性や実現したいコンセプトから「PWAはネイティブ アプリを潰そうとしているのか？」「Webアプリがネイティブアプリにかなうはずない！」など当該テーマにおいては辛辣なコメントを見かける場面もあります。ここで1つお伝えしたいことは、多くのユーザーはネイティブアプリなのかWebアプリなのかというプラットフォームの選択には関心がないということです。大事なのは「うまい、やすい、はやい」ユーザー体験の良いサービスを提供することです。PWAの出現によりWebアプリでもそれを実現する準備が整いつつあり、<strong>事業者やソフトウェア エンジニアとしては理想のサービスを提供できるプラットフォームのオプションが増えるという意味で、このWebの進化を前向きに捉えていただければ幸いです。</strong></p>

<p>実際Webアプリにはまだできないこともあります[7]。ただし、Webアプリには他のプラットフォームよりも優れたリーチがあり、<strong>その意味でWeb アプリとネイティブ アプリがむしろ手を取ることは、戦略としても決して矛盾しません。</strong></p>

<p><img src="/wp-content/uploads/2018/04/pwa06.png" alt="pwa06" /></p>

<p>使用したい機能がWebプラットフォームが提供するもので十分であり、技術スタックをWebのみに集約するメリットも感じるのであれば「PWA のみ」という選択肢も今後は出てくるかと思います。しかし、前述した「まだできないこともある」という前提を加味するとネイティブアプリが活躍する場面は引き続きありますし、<strong>PWAは「Webアプリ vs ネイティブアプリ」という二者択一を迫る提案ではない点をご理解ください。</strong></p>

<h2>ユーザー体験の新たな基準</h2>

<p>このようにPWAはWebアプリの「ユーザー体験の新たな基準」を満たすために作られたベストプラクティスでしかありません。重要なのはそれぞれの機能を単純に実装するのではなく、Webアプリの特性に応じて使い分け、ときにはカスタマイズし、ユーザーによりよいサービスを提供することです。今回ご紹介しました各種ツールやデザインパターン、iOSでもService Workerが利用できるようになった点など、舞台は整いつつあります。<strong>ぜひとも最高のWeb体験を実現すべくPWAの考え方を取り入れてみてください。</strong></p>

<ul>
<li>[1] <a href="https://www.doubleclickbygoogle.com/articles/mobile-speed-matters/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">The need for mobile speed: How mobile latency impacts publisher revenue</a></li>
<li>[2] <a href="https://developers.google.com/web/fundamentals/performance/rail" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">RAILモデルでパフォーマンスを計測する</a></li>
<li>[3] <a href="https://youtu.be/_srJ7eHS3IM" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Fast By Default: Modern Loading Best Practices (Chrome Dev Summit 2017)</a></li>
<li>[4] <a href="https://infrequently.org/2017/10/can-you-afford-it-real-world-web-performance-budgets/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Can You Afford It?: Real-world Web Performance Budgets</a></li>
<li>[5] <a href="https://support.google.com/adsense/answer/132618" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Above the fold</a></li>
<li>[6] <a href="https://www.windowscentral.com/first-batch-windows-10-progressive-web-apps-here" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">First Windows 10 Progressive Web Apps (PWA) published by Microsoft hit the Store</a></li>
<li>[7] <a href="https://whatwebcando.today/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">What Web Can Do Today</a></li>
</ul>
]]></content:encoded>
			</item>
	</channel>
</rss>
