エンジニアHubPowered by エン転職

若手Webエンジニアのための情報メディア

PWAで表示速度が2倍に! スピード改善を妥協しない日経電子版に学ぶ、PWAのメリット&デメリット

ネイティブアプリに近い体験を簡単に提供できるとして注目を集めている「PWA」。実際に導入し、表示速度が2倍になったという日経新聞電子版の開発者に「PWA」のメリットとデメリットを伺いました。

PWA(Progressive Web Apps)は本当に「アリ」なのか――?

ネイティブアプリの開発にはWebとは異なる専門知識が必要であり、またAndroidやiOSなどOSごとでも異なるため、リソースが膨大にかかるという課題があります。そこで昨今は、XamarinやReact Nativeなどのクロスプラットフォーム開発ツールを使い、ネイティブアプリやWebの開発を一本化しようという動きが活発になっています。

一方で、ネイティブアプリに近い体験を簡単に提供できるとして注目を集めているのが、Googleを中心に策定されている技術「PWA」です。2018年3月にはSafariにもService Workerが実装され、より開発が盛り上がっています。

そんな中、日本経済新聞社が提供する「日経電子版」は、2016年ごろからいち早くPWAを利用した開発を進めてきました。その効果は絶大で、特定のページではネイティブアプリよりも速度がでるまでになったそうです。


日経電子版をホームに追加するとネイティブアプリのような体感が得られる。タブもChromeなどのブラウザとは別になる

そこで、日経電子版を担当するエンジニア・宍戸俊哉さん、安田竜さんのお二人に、開発のノウハウや課題、ネイティブアプリとの関係など、PWAを使った開発のノウハウをインタビューしました。

宍戸俊哉(ししど・しゅんや/@sisidovski)(写真右)
2012年に新卒でドワンゴに入社し、2016年の4月に日本経済新聞社入社。ドワンゴではニコニコ静画などのサービスに携わり、フロントからサーバサイドまで幅広く業務を担当。現在は、日経電子版のCDN周りなどを担当し、新卒向けの研修など若手エンジニアの土台づくりにも従事している。
安田 竜(やすだ・りょう)(写真左)
2015年、新卒でNTTに入社し翌年に日本経済新聞社入社。大学ではセキュリティソフトウェアの実装などを行い、NTT在籍時はDockerなどのコンテナ仮想技術関連を研究していた。現在はPWA周りのService Worker開発などを担当するほか、機械学習関連の業務にも着手している。

速度改善を追い求めていたら、PWAにたどり着いた

―― 日経電子版にPWAを導入した「きっかけ」を教えてください。

宍戸:2015年に会社がイギリスの経済紙『Financial Times』を買収したのですが、向こうの開発陣にWorld Wide Web Consortium(W3C)などで活躍している方がいたんです。彼らといろいろと議論する中で、2016年ごろから「アプリだけでなくWebも内製開発を進めて、先端的な仕組みや技術を採用していこう」となりました。

僕らのチームの一番大事なKPIは「速度をあげる」こと。当時そのKPIを達成しようと思うと、必然的にService Workerが選択肢として浮かんできて。2016年にサイトに導入したので、取り組みとしてはかなり速い方だと思います。

Service Worker
PWAの根幹にある技術で、通常のWebページとは別のバックグラウンドで独立して動くスクリプト。オフラインでの操作やプッシュ通知などが行える。

そもそも、開発当初は「PWAをやっていくぞ」という感じではなかったんです。「速度を上げるためにService Workerを使いましょう」というところから始まって、速度改善に取り組んでいたら、たまたま「PWAが良さそう」という潮流があって、これいいんじゃないと。

個人的に、PWA自体はリリース当初から注目していて、2015年のアドベントカレンダー記事で紹介したりしていました。学んでいた知識がチームで使えたのはよかったですね。

―― Service Worker周りの開発は、安田さんが中心となって行っていると伺いました。会社として導入する前に「Service Workerは良さそう」という感触はあったのでしょうか?

安田:少し触ってみてすぐ、AppCacheよりは扱いやすく、プログラマブルで良いなと思いました。ただ当時は「Workbox」などService Worker周りのライブラリがなかったので、ゼロからコードを書いて、フレームワークの再実装みたいなことをしていました(笑)

Workbox
Service Workerのキャッシュ管理などを自動で行なってくれるライブラリ

宍戸:あと、Service Workerを素で使っていると、キャッシュの状態管理が難しかったんです。今から開発するとしたら、絶対にWorkboxみたいな抽象化されたレイヤーから使えるライブラリを使うと思います。

ネイティブアプリに「近い」ところまできている

――ずばり、PWAを導入してみて実感したメリットは?

宍戸:やっぱり速度ですね。スマホのホーム画面に追加したユーザからのアクセスで、良い結果が出ているんですよ。速度が上がったことで、通常の1セッション当たりの閲覧数が過去の数値に比べて、ホームに追加したユーザーのアクセスは約2倍になっています。詳しくはこの資料を見てもらえると。

Service Workerなしの速度

Service Workerありの速度。旧サイトと比較すると50%程度の速度改善が見られる(3G環境)


Lighthouse(パフォーマンス測定ツール)のスコア

面倒くさくてネイティブアプリをインストールしないユーザーが、ホーム画面から日経電子版にアクセスする頻度が高くなっているというのは良い傾向だと思います。サイトの表示が1秒遅いとコンバージョン率が何%落ちます、といった指標もありますし。

―― PWAの導入後、実際にユーザから速度に関する反応はありましたか?

宍戸:はい。「速くなったね」と。Service Workerでトップページや静的なものをキャッシュしているので、それが体感速度を上げた要因になったんだと思います。実際、PWA導入の翌週に表示の速さが話題とになり、Twitterのトレンドに「日経電子版」が入るくらいでした。サイトの速度がトピックとして取り上げられたのは良かったかなと。

Google I/O 2018でも、Webパフォーマンス改善のセッションで事例として紹介された

―― 一方で「PWAではネイティブアプリの速度に勝てない」という話も耳にします。その辺りはどうでしょう?

宍戸:確かに、よく議論になりますね。Androidでは、PWAを実装したWebの方が記事の表示速度は速い場合があります。iOSではまだ勝てていないですね……。


Androidアプリ(左)と、PWAで実装されたWebサイト(右)の速度比較。若干ではあるが、PWAを実装したWebサイトの方が早い

安田:僕らはSPA(Single Page Application)構成ではないので、ページをキャッシュするためにService Workerを使ってキャッシュの処理をゴリゴリと書きますが、ネイティブアプリの開発では手元にJSONを置いておいてロードするだけで済みます。日経では、開発の手間を考えるとやはりまだネイティブアプリの方が上だと思います。

SPA
Webアプリケーションのアーキテクチャ。単一のページでコンテンツの切り替えができる

宍戸:ネイティブアプリはマルチスレッドを扱う仕組みがちゃんと用意されているけれど、ブラウザはまだ使いやすい状態ではない。実際に60fpsで常に描画して……とかは簡単ではないですし、そこに難しさがあるなと感じます。

トータルすると、まだまだネイティブアプリの方が良い体験ができると思います。けど、速度に関してはけっこう「近い」ところまで来ているんじゃないかな。

安田:僕もそう思います。比較的、ネイティブアプリに体験を近づけやすい分野ではあると思うので。

正直、バグはめちゃくちゃ多かった

―― PWAの導入で苦労した点は?

宍戸:ユーザーの状態管理とキャッシュをどう管理するか、です。正直、かなりのバグが発生しました(笑)

日経電子版は、有料会員にはコンテンツを見せるけど、無料会員には見せないという仕様があって、ユーザーの状態によってキャッシュを出し分けるという制御が必要なんです。そのService Workerが持っているキャッシュと、ユーザーの状態をちゃんと同期させないと、有料会員じゃないのに記事が見えるといった、ビジネスとしてクリティカルな問題が発生しうる。キャッシュの同期は、かなり気を使いました

開発の初期は、有料会員にページが表示されないなど、ユーザ情報のキャッシュがうまく動いていなかった

あとは、SPAでService Workerを使う場合、静的なもの以外、キャッシュする中身の形式はだいたいJSONだと思います。日経電子版ではSPAのようにAPIをフロントで叩いて、サーバとデータをやりとりするというものではなくて、サーバからHTMLが返ってくる昔ながらの形式でやっています。

なのでHTMLはキャッシュしてるけど、HTMLのheadの <link> タグに書かれているCSSはキャッシュできていなくてスタイルがまったく適用されていない、といったバグもありました。そのバグには、HTTPのLinkヘッダーに全部の静的リソースを入れ、それをパースして追加でキャッシュする、という対処をしました。

今はService WorkerやPWAの話はSPAが前提だけど、僕たちは先人の恩恵を受けられずに自分たちで開拓しながら開発していました(笑)

―― サイトをSPAに変更しよう、といった議論はなかったのでしょうか?

宍戸:Reactを使ってみようか? という話はありましたが、当時はまだ「Reactはデファクトスタンダードでいけるのか?」「フレームワークのライフサイクルが長く続かないんじゃないのか?」という懸念がありました。今はフロントエンドのトレンドが落ち着きつつありますが、そのときはまだ分からなかった。

あとは一般論として、SPAを使うとフロント側の状態管理がめちゃくちゃ大変になるので、保守性の関係から長い目で見るとサーバ側で処理した方がいいんじゃないかという判断になりました。

安田:日経電子版は、ユーザーが頻繁に投稿や書き込みをするような“動きがある”サイトではないので、サーバサイドレンダリングでキャッシュした方がパフォーマンスが良くなるという理由もありました。

サイトの特性に合わせた工夫でキャッシュ問題をカバー

―― Service Workerのキャッシュが走るとユーザーの通信に負荷がかかりそうなイメージがあるのですが、その辺りはどう対処しているのでしょう?

安田:実は、全ユーザーに対してService Workerのキャッシュを効かせているわけではないんです。例えばTwitterから一つの記事を見るためだけにアクセスしたユーザーはキャッシュしなかったり、ホーム画面に追加したユーザーとそうでないユーザーでキャッシュの量を変えたりしています。不要なキャッシュで容量が増えないような工夫をしています

宍戸:日経電子版はサービスの特性上、一度記事を読み終えると、もう一度読み返すことがなかなかない。なので、基本的にユーザーがアクセスした「記事」に対してはキャッシュを入れていないです。例えばECサイトであれば何回も同じページを行ったり来たりするので、キャッシュするべきだと思います。キャッシュAPIの容量は、完全にブラウザ任せなので、この辺りは気を付けた方が良いですね

また、今は一時的に機能から外していますが、朝刊、夕刊の記事を毎日読むユーザーもいるので、記事一覧を全部先読みしてキャッシュし、オフラインであっても一気に読める仕様にしたこともありました。一気にキャッシュすると通信量が増えそうだったので、Network Information APIという、ユーザーが使用しているブラウザの通信環境を取得できるAPIを使って、Wi-Fiのときだけ先読みするようにしていました。

通信に関してはNetwork Information APIを利用して制御していた

もう一つ、IndexedDBにキャッシュしたデータとタイムスタンプを記録しておいて古くなったものから削除していく、という処理もしていました。近々またこの機能は入れる予定ですね。

―― なぜ記事一覧の先読みキャッシュ機能をオフにしたのでしょうか?

宍戸:A/Bテストで5%〜10%のユーザに機能を公開したところ、ログイン前後のキャッシュ同期周りで、ログアウトした後にキャッシュが消せていなかった不具合が起きたので、一時的に消しました。また、ブラウザの仕様によって不具合が起きることもあるので、解決が難しい場合もあります。

―― なるほど。今年の3月にSafariもようやくService Workerに対応したようですが、そういったブラウザ間の問題はこれからも起きそうですね。

宍戸:そうですね。実際に、SafariのService Workerが動いていても、呼んだ後に返ってくるべき値がnullで返ってきたり……。SafariはService Workerが入ったもののWeb Pushを有効にできないので、そういう挙動になっているようですね。

そういった問題は、テクノロジープレビューで確認し、次のSafariの早期リリースバージョンのタイミングで同様の問題が起きないかチェックしています。

安田:開発当初はService Worker周りの実装や開発環境がまだ発展途上だったため、ブラウザによってはバグがありました。例えばFirefoxは特定の条件下でService Workerからのレスポンスがめちゃくちゃ遅くなった。大変だったのは、そういうバグが発生しても参考にできる資料が何もないから、ひたすら試すしかなかったこと。バグ報告も直接Mozillaにしたり……。

実質、デバッグができたのはGoogle Chromeだけで、Firefoxは開発者ツールが充実してなかったため、まともなデバッグができず、開発が困難でした。今ではそういったこともほとんどないんですけどね。

PWAの「向き」「不向き」

―― PWAを導入すべきサイトといいますか、「向き」「不向き」はあるのでしょうか?

宍戸:日経電子版と同じように、「記事」を読ませるサイトはユーザーに良い体験が提供できると思います。実際、僕らと同じようなメディアサイトでPWAを導入している企業も増えてきているのかなと。あとはWebでの決済サインインなどもアプリの体験に近づけられる技術が出てきているので、より多くのサービスが導入できるようになってくると思います。

「向いてないサイト」という視点だと、AppleのARKitやPixelの写真専用のビジュアルコアチップなど、端末やOSよりの機能へのアクセスはしばらくできないと思うので、そこは引き続きネイティブアプリが強い領域かなと思っています。

―― なるほど。ではもし、これからPWAを導入する企業のエンジニアから「PWAだけでネイティブアプリは作らないんだけど……」と相談されたら、どのように回答しますか?

宍戸:僕は「PWAだけでもあり」です。

安田:そうですね、レスポンシブなPWAをつくっておけば、PCもモバイルもアプリ相当のものも一本のコードで管理できるので、それができれば理想形かなと思います。

宍戸:むしろ、これから新規サービスをリリースする際にネイティブアプリを中心に開発するのはリスキーなのでは? と感じていています。React NativeやFlutterなどの導入事例を見ていると、「一つのコードで動かそう」という流れもあると思います。

今のスマートフォンユーザーってインストールするアプリを厳選している印象がある。毎月必ず新しいアプリをインストールしている人って、けっこう少ないと思うんです。アプリストアにネイティブアプリがあるのはメリットとデメリットの両方あって、気軽にアクセスできてどんどんユーザーのエンゲージメントを高められる点は、PWAの強みですね。

―― ネイティブアプリとWebの関係がどんどん曖昧になっていきそうですね

宍戸:日経電子版に限らない話ですが、Webとネイティブの関係を考えるとWebAssemblyは注目するべきと考えています。PWAが世の中にもっと浸透したときに、現状のJITコンパイラで動くJSでは、提供できるものに限界がある。

WebAssembly
ブラウザでアセンブリ(機械語)を実行できるようにする技術。2015年ごろより進められており、現在WebAssemblyへのコンパイルが可能なのはC/C++、RUST。

WebAssemblyの技術が普及していけば、よりネイティブアプリと同じような体験ができるようになるのかなと思います。ネイティブと同じことがWebで出来るようになったら、業界的にはどんどん変わっていくんじゃないかなって。

ブラウザの描画エンジンに直接アクセスできる仕組みも徐々に整っていくと思っていて、2020年代には、また大きくWeb業界は変わっているんじゃないかと個人的に思っています。

PWAを導入する前に押さえておきたいポイント

―― よく「PWAは導入が簡単」だと言われていますが、導入してみて分かった学習コストなどを教えてください。

安田:今やService Workerそのものは資料がたくさんあるので、学習コストはそこまでかからないと思います。ただ、どういうコンテンツをキャッシュするかや、どういうタイミングでキャッシュすると効果的かなどはサービスによって異なるので、キャッシュ周りの知見は導入してみないと分からない部分が多い

宍戸:あと、Service Workerのライフサイクルは少しだけでも理解しておいたほうがいいと思います。

僕らが開発していたころは、まだブラウザと戦うような段階だったんです。Google ChromeでService Workerを一時的に無効化するオプションを使用していたんですが、実はそれが動いてなくてService Workerが意図しない挙動をする、みたいな。今は直っていますが。

安田:キャッシュ関連のService Workerのコードは700行くらいで、今ではライブラリで実装されているようなユーティリティ関数も少なくないので、ロジック部分はそこまで時間がかからないと思います。

宍戸:動的なものがあまりなく、静的リソースやトップページのキャッシュ周りだけであれば、半日もあれば出来るかと。凝ったことをしなければ本当に簡単で、ロジック的な難しさはない。でも、ユーザーの状態や古いキャッシュの削除など、キャッシュ管理の面ではまだまだ難しさがありますね。

あと、メジャーなフレームワークはPWA用のモジュールが公開されていたりするので、それを使えば自分でService Workerのコードもほとんど書く必要がないかもしれません。

―― デプロイについても教えてください。

安田:特別なことはしておらず、他と特に変わらないです。CI(継続的インテグレーション)でツールを動かして、中でSeleniumが動いて、Service Workerの挙動を確認して……というE2Eテストを動かすようにはしています。

―― デプロイしたときにService Workerを更新すると、古いキャッシュと新しい処理で不具合が起きそうですが、そこはどう対処しているのでしょう?

安田:新しいService Workerがactivateされたときにパージするような処理を入れたり、キャッシュのバージョニングを行っていたりします。

宍戸:ユーザー側からすると、データ通信量がムダになるかもしれない可能性もありますが、「安全」を取った方がいいかなと。

―― ブラウザごとの違いもありますし、まだ確立された方法がなさそうで、テストが難しい印象があります。

安田:当時はGoogle Chromeでしか安定したE2Eテストができない環境だったので、そのまま今もGoogle Chromeにしか対応できておらず……。ただ、SafariでService Workerが動くようになってきましたし、他のブラウザのテスト対応もしないといけないというのは感じています。

あとは手動になりますが、ローカルの環境でService Workerを立ち上げて、ローカルプロキシを使い本番環境で動いているService Workerだけ自分のに差し替える検証はしています。

―― 先ほど「先人の恩恵を受けられずに自分たちで開発している」とおっしゃっていたように、開発当時はまだ参考にできる資料がかなり少なかったと思います。例えば、開発に当たりGoogleが提唱している「PRPL」などのデザインパターンは参考にされなかったのでしょうか?

宍戸:PRPLなどのデザインパターンはApp Shell モデルと言って「SPAの中でこういうやり方をするといいですよ」というベストプラクティスの中の一つなんです。さっきも話した通り僕らはSPAではなく、サーバがHTMLを返す昔ながらの仕組みでやっているので、そのままは適用できないんです。

PRPL(パープル)
Googleが提唱しているPWAを開発する際のデザインパターンの一つ。PRPLは以下の4つの頭文字から名付けられている。
Push:最初のURLルートに不可欠なリソースを Push(プッシュ)する
Render:最初のルートを Render(レンダリング)する
Pre-cache:残りのルートを Pre-cache(事前キャッシュ)する
Lazy-load:オンデマンドで残りのルートを Lazy-load(遅延読み込み)する

安田:それに、開発を始めたときは「PRPL」自体知らなかったというか、まだなかったタイミングだったかもしれないです。

宍戸:PRPLに近いことはやっていると思うんですが、強く意識して実装したというわけではないですね。やはりPWAやHTTP/2などの最近の「Webのベストプラクティス」を集めていったら自然とこういう形になった。だから、突き詰めると自然と似通う部分も出てくると思います。

具体的には、日経電子版は各ページにJSやCSSが独立していて、ルートごとに存在するイメージなんです。それらをHTTP/2のサーバプッシュを使い、先に読み込んでレンダリングをしている。レンダリングをしたら、Service Workerがトップページの記事をいくつかキャッシュ。ここでPRPLでいうプリキャッシュ(P)をして、次にレイジーロード(L)で読み込んであげる、という仕組みにはなっているから、パターンが近いと言えば近いと思います。

PWAには確かに課題が多い。しかし強みもある

―― いろんな開発の裏話を教えてもらいましたが、実際にPWAでサービスを運用してみて感じたデメリットをまとめると?

宍戸:キャッシュ階層が一つ増えるので、キャッシュ管理の大変さがあります。アプリケーションでキャッシュを持って、CDNでキャッシュを持って、ブラウザキャッシュがあって、Service Workerのキャッシュがあって……どこにキャッシュがあるんだよって状態になります。Service Workerを入れると、複雑性が一つ増すんです。

今もまだ、意図せず古い記事が表示された場合にどこでキャッシュされているのか調査するのが大変だったりします。

安田:そうですね。記事ページには、キャッシュの中身を表示させた後に中身を比較して、古かったら新しい記事を表示させるなどの処理はしていますが……。

宍戸:以前はモバイルがGoogle Chromeしか対応しておらず、Safariで使えないというのが大きなデメリットでしたが、それがなくなったのでService Workerを使うメリットの方が多くなったかなとも感じています。

―― 先ほども少し話があったようにSafariはpush通知がまだ実装されていません。こういった場合、開発はSafariのバージョンアップに合わせるのでしょうか?

宍戸:基本的にPWAは、Webの標準技術要素だけで実装されているので、開発を進めておいて後からSafariが付いてくる、というのが正しいと思います。そもそも、Google Chrome向けに作ったものがSafariでも動くべき実装で構想されているので、Safari向け対応というのは、本来あってはならないと考えています。

Progressive EnhancementというWebデザイン戦略の考え方では、「あらゆるユーザに対応しつつ、高機能なブラウザはよりリッチな体験ができるようにする」ということを推奨しています。日経電子版もその考えに沿った開発をしていければいいなと思っています。

ただ、そうは言っても対応しないといけない問題もある。Safariがpush通知に対応してないのは、エラーなくちゃんと動くようにエラーハンドリングを工夫するコードを書いています。

ただ、もうひとつクリティカルな問題があって……。Safariも今はWeb App Manifestを読むようになっていて、ホームに追加するとPWAのようにサイトが立ち上がるんです。でも、普通のiOSアプリと違っていて、いわゆる「エッジスワイプで戻る」が効かない。

日経電子版は画面内に「戻る」ボタンを用意していないので、記事から戻りようがないんです。その辺りは、Safari向けの仕様にしないといけないなと。

―― なるほど。話を伺っていると、PWAにはまだまだ課題がありつつ、スマホアプリのように動くのはやはり強みだと思います。今後、日経電子版のネイティブアプリとの関係はどうなっていくのでしょうか?

安田:正直に話すと、それぞれ別ベクトルの強みがあると思っています。PWAは手軽に実装できるし、ストアを通さなくて良いというメリットがある。でも、ブラウザという制約がある以上、ネイティブアプリほどのUXは提供できない。

例えば、ネイティブアプリは隣のタブにスワイプで移動できますが、ブラウザ上でスワイプするとブラウザバックになるので、ブラウザの枠組からは抜け出せないというどうしようもなさはあります。だからこそ、ヘビーユーザーにはネイティブアプリを使ってもらって、そうではないユーザーに向けてアプリに近いUXが提供できる手段としてPWAが役立つと思います。

宍戸:だいたい同じ意見です。今と変わらず、エンゲージメントの高いユーザにはネイティブアプリを使ってもらいたいです。Twitterなどのソーシャルサービスから日経電子版にどんどんアクセスしてもらう「玄関」がモバイルのページだと思っているので、そういった点でより使いやすいものになっていければいいかなと考えています。

―― 今後、日経電子版でPWAやService Worker周りの課題はありますか?

安田:PWA周りでは、これまでは速度改善が中心だったので、UX/UIがネイティブに近づいていないという課題があります。ネイティブアプリとモバイルで見た目が同じなのに、挙動が違うとユーザーは混乱すると思うので、体感をアプリにどんどん近づけて、直感的に操作できるようにしたいですね。

宍戸:同じく。もちろんUX/UIも大事にしたいけど、でもやっぱり速度も上げていきたいです!

―― もう十分速いと思うのですが、まだ改善していくんですね!

宍戸:まだ上がると思います!

安田:丁寧にやれば、まだ伸びしろはあると思います!

―― どこまでもスピードを追求する姿勢に一貫性を感じました! 本日はありがとうございました。

取材:megaya megayaのブログ

【修正履歴】初出時、Lighthouseのスコア画像に誤りがありました。ご指摘により修正しました。(2018年6月5日12時30分)