PWA, PRPL Pattern の概要と採用状況の調査
こんにちは。メドレーにてジョブメドレー開発エンジニアをしています、矢野と申します。
- ジョブメドレーでは、主にバックエンド ( Ruby on Rails ) の改修を担当してます
- 直近では 「サイトパフォーマンス改善施策」 として、Rails コードのリファクタリングによる TTFB 高速化に取り組んでました
- 「もう絶対にコケないのが分かってる」ビルドやテストを、手元のコンソールで何度も叩いて「わー。ちゃんと通る!」っていう時間が好きです
今回は、上記の「サイトパフォーマンス改善施策」の文脈で調査した、PWA の実装パターンである PRPL Pattern という リソース提供の設計アーキテクチャ について紹介します。
PRPL Pattern とは
PRPL Pattern は、Google I/O 2016 で提案された PWA - Progressive Web Application の構築・配信のための設計アーキテクチャです。
Web サイト・アプリケーションが、回線強度やスペックが高くないスマートフォンなどのデバイスでもストレスなく機能するよう、リソース配信とアプリ起動時のパフォーマンス ( = 高速化 ) に重点を置いています。
PRPL meanings
では具体的に「どうやって速くするの?」ということで、PRPL が提唱している 4 つのサイトレンダリング手法について見ていきます。
- Push:
<link preload>
および HTTP/2 を使用して、初期 URL ルートの重要なリソースを Server Push する - Render: クライアントが初期ルートをなるべく早くレンダリングする
- Pre-cache: 残りのルートをクライアントが Service Worker でプリキャッシュする
- Lazy load: クライアントはオンデマンドで残りのルートを遅延読込みして作成する
PRPL は上記 4 つの頭文字をとったものですね。 PRPL は HTTP/2 の Server Push や、PWA の Service Worker など、Web プラットフォームの最新技術を駆使してサイトパフォーマンスをあげよう!というプラクティスです。
PWApps とは、最新の Web 技術を有効に活用し、漸進的 ( Progressive ) に高度なユーザー体験を提供しようとする概念です。この PWApps の概念を具体化する一つの手法として、「 PRPL 」 ( パープル ) と名付けられた開発・提供パターンが提案されました。
(中略)
Web Components や、 Service Worker、 HTTP/2 Server Push といった Web の最新技術をフルに活用し、レスポンス性の高いユーザー体験を提供しようというものです。
ref. Google が新たに提唱する Progressive Web Apps の新たな開発パターン「 PRPL 」とは?
周辺知識 - HTTP/2
まずは、周辺知識からおさらいしていきます。PRPL は HTTP/2 の Server Push を利用する、という話でした。そもそも HTTP/2 とはどんなものでしょうか。
- Hyper Text Transfer Protocol と呼ばれる TCP 上の通信プロトコルの次世代バージョン
- 普段私たちが Web サイトを閲覧する際に利用しているプロトコル
- HTTP/1.1 が 1997 年に策定され、2015 年にようやく /2 が標準化
- Express, Apache, Nginx など各 Web サーバ、各ブラウザも対応してきている
ref. HTTP の進化
現行の一般的なバージョンは HTTP/1.1
HTTP は普段私たちが Web サイトを閲覧する際に利用する通信プロトコルです。HTTP/2 はその次世代バージョンになります。HTTP/1.1 には以下のような特徴があります。
- ステートレスな通信
- テキストベースで情報をやりとりする
- 原則 1 リクエストに対して 1 レスポンスである
- → 複数リソースを得るために何度もリクエストしてコネクションを貼り直す必要があり パフォーマンス上の課題がある
これに対して、1.1 の次期バージョンである HTTP/2 は以下のような特徴があります。
- 通信時にヘッダを圧縮し使い回す省エネ設計 = 一部ステートがある
- バイナリベースで情報をやりとりする
- ストリームという概念で、1 コネクション中で Request / Response を多重化できる
- → 1 コネクションの中で複数リソースを並行して Request / Response できる!
- リソースの Server Push が可能
HTTP/2 自体が HTTP/1.1 の課題であった通信のオーバヘッドを改善する規格であることがわかりますね。また「 request / response の多重化」により、1.1 と比較してどの程度「速く」なるのかについては、以下 Akamai 社のブログサイトが参考になります。
HTTP/1.1
HTTP/2 ( request / response の多重化 )
HTTP/2 の採用事例
ref. caniuse.com
上記対応状況からも分かる通り、モダンブラウザでは一通り対応しています。実際のプロダクションでも 日本ではメルカリさん、世界的なサービスだと Twitter, Facebook, Instagram など SNS サービスや、Slack, Dropbox などが HTTP/2 に対応しているようです。
ジョブメドレーはまだ HTTP/1.1 でのサービス提供しか行っていませんが、ゆくゆくはバージョンアップ対応を行っていきたいと思っています。
周辺知識 - PWA
次に、PWA についておさらいします。PRPL は PWA の Service Worker を利用した実装パターンという話でしたが、そもそも PWA や Service Worker とはどんなものなのでしょうか。
PWA - Progressive Web Application
- Web プラットフォームの新機能を使って「ネイティブアプリとウェブアプリのいいとこ取りした、UX の高いウェブアプリ」という概念
- ウェブアプリの特性 ( Secure, Linkable, Indexable … ) を保ちつつ、ネイティブアプリの多機能さ ( インストール、プッシュ通知、オフライン動作 … ) を最新のブラウザ機能 = JavaScript API で実現する
- 必ずしも SPA であったり、最新機能の全てを使っている必要はなく、「斬新的に Web 新 API でネイティブな機能を取り入れていける」というコンセプト
PWA を構成する新機能たち
- HTTPS: HyperText Transfer Protocol Secure 、 SSL / TLS による通信の暗号化
- Service Worker: Web ページで動作するスクリプトから独立したイベント駆動型の worker
- Cache API: Request / Response オブジェクトのストレージキャッシュ
- Push API / Notifications API: サーバーからアプリへの通知送信
- マニフェスト: アプリストアを通さず Web アプリをホーム画面にインストール可能
ref. プログレッシブウェブアプリ - MDN
上記以外にも、PWA には様々な API ・機能が存在します。その中でも PWA の、そして PRPL アーキテクチャの中核を成す重要な機能が Service Worker です。
Service Worker とは
- ブラウザのバックグラウンドプロセスとして動作する Worker
- Web ページで動作するスクリプトとは独立して動作する
- サーバサイドでいうところの Worker プロセスと同じような使い方ができる
ref. Service Worker の紹介
Web ページの JavaScript プロセスとは切り離された文脈で、予め登録しておいた処理を、様々なイベントに応じて発火させることができるイメージですね。
プッシュ通知など、いわゆる「ネイティブアプリのような機能」は、この Service Worker を利用することで実現しています。
PWA の採用状況
Google からの提唱当初 ( PWA も Google のプロジェクトです ) こそ、先進的すぎてなかなか受け入れられなかった PWA ですが、2020 年現在は各ブラウザの対応状況も少しずつ向上されています。
日本では SUUMO、日経電子版、一休.com、世界的なサービスだと Instagram などが PWA による Web サイトを提供しているようです。
- リクルートの『SUUMO』、Android スマートフォン用サイトでプッシュ通知できる機能を実装
- PWA で表示速度が 2 倍に! スピード改善を妥協しない日経電子版に学ぶ、PWA のメリット&デメリット
- なぜ Instagram は PWA を作ったのか?
特に、既にネイティブアプリで大成功している Instagram が、回線・端末スペックの低い新興国をターゲットとした PWA をリリースしているという点はプロダクト観点からもとても興味深いですね。
PRPL パターンの利点
さて、話を戻して PRPL パターンが HTTP/2 や Service Worker を使って、具体的にどのようにサイトパフォーマンスを向上するのか?という点を見ていきます。
Server Push + Service Worker による Pre-cache
PRPL の 4 要素を、改めてもう少しわかりやすく記載してみると以下のようになります。
- Push
- 初回コネクションで HTTP/2 Server Push で 必要リソースをまとめて Push
- Render
- 上記で受け取った HTML リソースを元に初期画面をレンダリングする
- Pre-cache
- 上記初期画面で利用されるリソースは、Server Push により非同期的に Service Worker が Pre-cache する
- また、今後利用しそうな追加リソースについても、非同期・投機的に Service Worker が事前に DL 、キャッシュする
- Lazy load
- 初期画面以降で必要になった画像などのリソースを、画面スクロールなどを検知し、表示に必要になったタイミングで遅延読み込みする
上記の太字箇所を画像で説明すると、以下のようになります。
HTTP/2 ( Server Push )
HTTP/2 の Request / Response の多重化だけを利用したケースと比較すると、「ブラウザがページを解析して、必要リソースを Request する」よりも前に「サーバが必要リソースを強制的に Push 」しているのがわかります。
この Push されたリソースを Service Worker が受け取り → キャッシュ化することで 「ページ解析が終わった時点では既に必要リソースがブラウザにキャッシュされている」 状態となり、アプリの初回起動が速くなる、というのが Push & Pre-Cache の速度改善の仕組みです。
Service Worker で必要になりそうなリソースの事前キャッシュ
また、初期画面に必ず必要なリソース以外については、「このあと必要になりそう・なるはずの追加リソース」ということで、Service Worker に投機的に事前 DL → Pre-cache されることも可能です。
このあたりのキャッシュ戦略・導入事例は以下の一休さんの記事が詳しいです。
一休.com に Service Worker(Workbox)を導入しました
PRPL Pattern の採用状況
さて、そんなパフォーマンスに嬉しい PRPL Pattern ですが、HTTP/2、PWA 自体の普及率も高くなくまだまだプロダクションでの採用事例は少ない印象です。
- Google I/O で日経電子版が事例として紹介された話
- PRPL パターンを参考にした Service Worker を使ったキャッシュ、HTTP/2 Push でのリソース配信などが採用されている
- ライブラリでは有名どころだと Gatsby が標準対応、当たり前だが Google の Polymer ライブラリも PRPL パターンで実装されている
とはいえ、PWA 化している Web サイトであればパターンの適用はそこまで難しくありません。
また Next.js の PWA 化ライブラリ next-pwa では、Next.js 本体の Code Splitting 機能と連携した「 Service Worker での追加コード読み込み」をサポートするなど、このようなアーキテクチャパターンの潮流は今後も派生していくのかな?という気がしています。
まとめ - HTTP/2 + PWA + PRPL Pattern
まとめです。
- PWA とは
- Web プラットフォームの新機能を使った「ネイティブアプリとウェブアプリのいいとこ取りした UX の高いウェブアプリ」という概念
- PRPL パターンとは
- スマートフォンなど回線強度・スペックの低いデバイスのために、Google が UX 向上のために提唱する PWA の設計アーキテクチャ
- HTTP/2, Service Worker などを使って (リソースの) Server push, Pre-cache, Lazy load を行う
- プロダクトで使えるのか
- Web サイトの PWA をする/しているのであれば、サーバの HTTP/2 化をして、リソースの Push、Pre-cache を導入するのはパフォーマンス観点で十分検討できるのでは
- 但し、SPA + SSR 構成のサイトでは、Next.js などフレームワークのコード分割に寄せるのが今の所無難そうではある
今回は調査のみで、プロダクトへの実践投入は行いませんでしたが、今後プロダクトの PWA 化が企画されるような場合は、ぜひ導入してみたい技術だなと感じました。
以上、ここまで読んでくださり、ありがとうございました。