Author Archives: y.a

2017-09-13

Yomerumoのスマホページの表示速度が約半分にまでなった話

主にYomerumoのフロントエンドを担当しておりますGMOアドマーケティングのy.aです。

Yomerumoは芸能・エンタメ中心に、有名人の情報やニュースなど様々な情報を豊富に取りそろえているニュースサイトです。
http://news.merumo.ne.jp/

Yomerumoのスマホページ

アクセスの多くはモバイル端末からなのですが、以前からそのモバイルで表示速度の遅さに頭を抱えていました。

下記は遅かった頃(高速化施策を始める前)の表示速度です。

期間 Android iOS
[2017/01/01~2017/03/31] 平均読み込み時間(秒) 14.88 6.16

※Google Analytics調べ

遅いですよね。。Google Analyticsの「平均読み込み時間」はページビューの開始(ページへのリンクがクリックされたときなど)から、ブラウザで読み込みが完了するまでの時間を表すため、一概に「ページが表示されるまでの時間」とイコールとは限りません。ただそれでもiOSはまだともかく、Androidはここまで遅いとユーザーに不便を与えていることは明らかです。
これまでもCSS/JSファイルの圧縮やCSSスプライトなどの対応はしていたのですが、今年に入ってから「表示が遅い」「より根本的に見直ししてほしい」というご意見を内外から少しずつ頂くようになりました。

ということで3月から本格対応を始めたのですが、3カ月間の試行錯誤を経て出た表示速度の結果が以下の表です。

期間 Android iOS
[2017/01/01~2017/03/31] 平均読み込み時間(秒) 14.88 6.16
[2017/07/01~2017/08/31] 平均読み込み時間(秒) 7.77 3.23

※Google Analytics調べ

表示速度をそれまでの約1/2に改善出来ました!当然数値だけではなく、体感的にも早く感じられるようになっております。

今回はそのYomerumoで行った表示速度UPのための施策について皆さんに共有します。
なお以下で紹介する施策は全てフロントエンドの内容となりますのでご了承ください。


指標と計測ツール

対応するにしても、何がサイト表示を遅くしているか原因が分からないといけません。
そしてその原因を探るためには計測が必要です。

当初速度改善はPageSpeed Insightsを参考に進めていました。
https://developers.google.com/speed/pagespeed/insights/?hl=ja

ただご存知の通り「PageSpeed Insights」はベストプラクティスの達成具合を見ています。つまりサイトの表示を遅くしている原因を提示してくれるわけではありません。(もちろんベストプラクティスを達成していないことが遅い原因と言えなくもありませんが。)
そういう意味では提示内容を全てクリアしても必ずしも表示速度向上を達成できるとは言い切れないところがあります。
また今回は複数メンバーで週ごとに検証していたため、体感的な表示速度を定量的に、かつページ表示までの流れを詳細に、そして可能であれば問題点の共有が容易なものが必要となっておりました。

そこで新たな速さの指標として「Speed Index」、そしてそれを計測するために主に「WebPagetest」を使用することにしました。
https://www.webpagetest.org/

「Speed Index」は可視範囲内での表示速度の平均値を測る指標です。つまりファーストビューでの表示速度を表しています。「Speed Index」はスコアが低ければ低いほど描画が早いということになります。今回の目標としている体感的な表示速度改善の指標として一番合っていました。

黄色でハイライトした箇所が「WebPagetest」で計測したSpeed Indexの値
よく参考にしていたのは「Speed Index」を算出するVisual Progress

また何をもって早いと考えるのかという中で、よりユーザー視点でページの表示過程を確認できる「WebPagetest」のビデオキャプチャ(filmtrip)がとても役に立ちました。

filmstripの一例。3Gで計測したというのもありますが、他社メディア様と比べても遅いです。。

ChromeのDevツールでも「Performance」を使えばビデオキャプチャを確認できますが、「WebPagetest」であれば先の「Speed Index」のスコアとあわせてビデオキャプチャも撮れます。
記録可能なビデオキャプチャであるためチーム内で問題事項の共有が容易になりました。


遅くしていた原因

上記「WebPagetest」等で計測し分析を進めた結果、Webフォントアイコンの使用、JSの動的なコンテンツ表示処理などフロント側の実装の問題点がたくさん見つかりました。
ただその中でも一番表示速度に影響を与えていたのは「ファーストビュー時のリクエスト数の多さ」でした。

例えば当時のトップページでは、ファーストビューのタイミングでYomerumoからリクエストする外部JSの数は14~5、画像は20程度でしたが、広告から出される広告に関するリクエスト(js、imgなど)は約250以上近くありました。。

3月時点でのリクエスト数。この中のjsとimageの多くが広告表示に伴ってリクエストされたもの

結局その他諸々全て合計すると毎回ファーストビューの時点でリクエスト数は平均で340~400余に上りました。これでは遅いのも当たり前で、特に古い端末であればあるほどその影響が大きかったと考えています。

上記リクエスト数の結果、当然ロードするバイト数も大きい

今までも全く気付いていなかったわけではないのですが、先の「WebPagetest」で他のニュースサイト様の分析をしても、Yomerumoのリクエスト数の多さが表示速度に影響を与えているのは明らかでした。


どう対処したか

大きくいうと以下の2つです。
1. ファーストビューコンテンツの表示調整
2. リクエスト削減

1. ファーストビューコンテンツの表示調整

ファーストビュー内にあるコンテンツ、パーツなどの表示を早くする調整です。以下2つの対応をしました。

1-1. localStorageの活用

通信を伴って動的に生成する要素がある場合、Ajaxを使用していることがほとんどだと思いますが、非同期ですと最初の描画のタイミングに間に合わず、後でぽつっとそのコンテンツが出てくることがあると思います。YomerumoでもAjaxで取得しているところがあったのですが、それまではプレースホルダーも置くことなく空白のままでした。

そこでそう頻繁に更新のない箇所については、毎回Ajaxせず初回で一度jsonを取得後localStorageを使用してローカル内に保存し、アクセスから10分間は通信せずlocalStorageから出すように変更しました。

これ自体は表示速度の数値には大きく影響与えませんでしたが、通信をしない分早くコンテンツが表示されるようになりました。

1-2. ファーストビュー内にあるパーツの表示調整

一部のパーツで「Font-Awesome」(Webフォントアイコン)を使用していたのですが、これもロードされるまではその部分が空白となってました。
少しでも早く感じてもらうには、やはりなるべくネットワークに依存しない形にするのが一番です。
Yomerumoで言うと右上にメニューのためのハンバーガーアイコンがありますが、当初「Font-Awesome」で表示していたものを、CSSでの3本線(border+border-radius)に変えました。

またロゴ画像も以前はCSSスプライトで表示していましたが、サイズが大きくなりすぎたため、表示が遅れがちでした。
ファーストビュー内の画像は少しでも早く表示させるために先のCSSスプライトから切り離し、タグで出力することによって可能な限り最初の描画に間に合わせるようにしました。

ビデオキャプチャで見ると分かりますが、それまでと比べてコンテンツ・パーツの表示が早くなりました。以下Before/Afterの画像です。

Before. ヘッダのコンテンツがほとんど表示されていない
After. 最初の描画の時点でほぼ表示されている

2. リクエスト削減

2-1. JSをバンドル

読み込む外部JSの数が一般のサイトと比べても多すぎました(14~15)。
これはサイト内に古くから存在していたものは触れず、とりあえず追加に追加を重ねていったため、結果こんな数になってしまったのです。。(反省)

要らないものは除去、まとめられるものはまとめるのが一番です。
このタイミングで改めて各JSの役割・依存関係を徹底調査し明確にした上で、不要なものを削除、残ったものはまとめる(バンドル)ために「webpack」を使用しました。

結論から言うとJSファイル全てを「webpack」によるバンドル対象とすることはできませんでしたが、14~5ほどあった細かいJSファイルを3~4に減らすことに成功しました。

蛇足ですが、「webpack」はリクエスト削減より、バンドルすることでJS同士の依存関係をはっきり出来るのが大きな利点だと思います。確かにリクエスト削減目的で導入しましたが、結果「require」で組んでいくことでコードの見通しが大変良くなり、今後の保守を考えた上でも対応して良かったと感じています。
通常、既に運用が始まっているサイトでwebpackを導入するのは色々とハードルも多いかと思うのですが、これにより不測のトラブルを回避できると思います。

2-2. ファーストビューにないコンテンツはインビュー読み込みに変える

今回の施策の中で一番効果が大きかったのはこれです。
画像・広告についてはファーストビューで表示されるもの以外は全てインビュー読み込みに変更しました。

やり方の詳細は省かせていただきますが、ある要素がインビューになったらそれをトリガーとして、画像のリクエスト、広告のリクエストを起こすイベントの形に変えたのです。
おかげで今までファーストビュー時に約400あったリクエストが、修正後わずか約100リクエストほどになりました!

赤がBefore、青がAfter
当然バイト数も減ってます

かなり大きいですよね。体感的にも一番ビフォーアフターで違いがはっきりと感じられました。


まとめ

以上の対応の結果、それまでの表示速度の半分の速さを実現することができました。

それまで目標としていた某他社ニュースサイト様と比べても今は「Speed Index」、そして「Load」時間においても、画像も広告数もはるかに多いYomerumoの方が早くなりました。(それまでは全く手の届かないくらい差があったので達成したときは大変感慨深かかったです。。)
実施の過程で、途中いくつも失敗があったのですが無事表示速度改善ができたと言えると思います。
ただ進めれば進めるほど表示速度に関してはまだまだ改善余地あることが分かりました。もっと言えばもう少しUXを考慮に入れた丁寧な調整ができると感じております。

例えばユーザーが「何をもって早く感じるか」ということの分析もその一つです。
取組み通じて分かったのがファーストビューの「最初の描写」(Render Start)が少し遅くなろうとも「最初の描画時点で構成するコンテンツがほぼ揃っている」方が、「最初の描画が早くともコンテンツがあまり揃っていないもの」よりも体感的には早く感じることでした。

例えばページが2.0秒のタイミングでRender Startされようとも、その時にコンテンツが60%近くしか出ていないのであれば、3.0秒のタイミングで、コンテンツが80%出ている方がユーザー体験としても良いでしょう。

上がAfterで下がBefore。確かにBeforeの方が描画が早く始まっているが、コンテンツが40%台から描画されているためユーザー的に早いサイトと感じるかは微妙なところ

フロントエンドで言うと「非同期」というキーワードが表示高速化と結ばれがちですが、
先の気づきもあって今回対応していったなかで多少描画が遅くなろうとも、Render Start時点で可能な限りVisual Progressの比率が高くなるようにあえて「同期」的にした箇所もあります。
よりユーザーに快適に使ってもらうことを考えた場合、「非同期」にすることが100%「正」にならない可能性もあるかもしれません。

赤がbefore、青がAfter。Afterの方がRender Startは遅いものの赤より早く100%に達している

ただいずれにしても、高速化という点だけにおいてはファーストビューにないコンテンツは可能な限り後読みの形にすることは大事なはずです。
モバイル時代に最適化したAMPHTMLを見ても分かりますが「<amp-img>」「<amp-ad>」などこれらのカスタムエレメンツもビューポート等に応じて読み込みを遅らせたりしています。
インビュー読み込みにすることで、無駄なリクエストが発生しないためユーザーにとって望ましい形であることは間違いないです。
(ちなみにYomerumoはAMPにも対応しております!詳しくはこちら

今回紹介した施策以外でもサイト内で一部Resource HintsのAPIを使用していたり、その他まだまだ説明しきれなかった細かいことがたくさんやったのですが、現時点で効果のほどが定かでなかったためまた別の機会にお伝え出来ればと思います。
さらに今後SSL化対応すればService Workerの活用も視野に入りますので、対応した際にはまた共有出来ればと思います。

読者の方にとっては当たり前のことばかりだったかもしれませんが、表示高速化進めるにあたって「PageSpeed Insightsしか使用していなかった」あるいは「なかなか指針を決められない」場合などに、この記事が少しでも有用なものになりましたら幸いです。

今後もYomerumoはよりユーザーに快適にサイトを利用してもらうよう進めてまいります。

※本記事で提示した「WebPagetest」の計測値は全て「From: Japan – EC2 – Chrome – Emulated iPhone 6 – 3GFast – Mobile」の条件で出したものです。

2016-08-30

YomerumoがAMP対応しました!

こんにちは、
GMOアドマーケティングで主にYomerumoのフロント周りを担当しております、y.aです。

もう2016年の夏が終わるんですね。8月末といえば溜まりに溜まった夏休みの宿題の消化かと思いますが、Yomerumoも溜まりに溜まったタスクを消化してついにAMP対応しました!

AMP-ss

Yomerumoは芸能・エンタメ中心に、有名人の情報やニュースなど様々な情報を豊富に取りそろえているニュースサイトです。

無題
news.merumo.ne.jp

今回はまだAMP未対応の方向けに、
YomerumoがAMP化にあたって行った作業をシェアしたいと思います。

AMPとは

AMPとはGoogleが公表した「Accelerated Mobile Pages(AMP)」というモバイル端末でウェブページを高速で表示するためオープンソースプロジェクトです。

2016年2月末以降、Google検索結果の「トップニュース」の枠にて、カルーセルあるいはテキストリンクの下に「AMP」とラベルがついたリンクを見かけるようになったかと思います。

AMP-ss-2

これがAMPページへのリンクでして、クリックすると分かりますが表示までとても早いです。

AMPページ

これはAMP対応ページがGoogleのクローラーにキャッシュされ、リンクがクリックされた際にはそのキャッシュ済みのコンテンツが表示されるためです。
AMPの情報については他のサイトでも多く見かけると思いますので、ここでは詳細は省いて主にYomerumoでどのようにAMP対応したか流れを説明します。

AMP対応の流れ

基本的にはGoogle Developer Japanにて公表していた「AMP 導入ガイドの日本語版PDF」に沿って進めました。以下大まかな流れです。

1. URLパスの検討
2. AMPのためのテンプレート準備
3. 構造化データ用意
4. アナリティクス埋め込み

1. URLパスの検討

GoogleにAMPページをキャッシュしてもらうには元の記事ページ(正規のバージョン)の<head>タグ内に

が入ってることが必要です。

そのような仕組みのため、導入ガイドにもありますが、URLパスはどのようなものでも大丈夫のようです。

http://www.example.com/myarticle/amp
http://www.example.com/myarticle.amp.html

Yomerumoの場合は新たにAMP用のディレクトリを切る形にしました。

2. AMPのためのテンプレート準備

JavaScriptの削除

基本的には従来の記事ページをベースに進めていきましたが、JavaScriptは使用できないため、使用している箇所(記事本文下にある「Good」「BAD」ボタンなど)は泣く泣くAMPから削除いたしました。

タグの置換

今回最も苦労した点です。
AMPでは<img>タグなど一部のHTMLタグはそのままでは使用できません。通常のHTMLの拡張をしたAMPカスタムタグを使用することになります。
それぞれのタグについてはAMP Projectで公表しているので参照頂ければと思います。

YomerumoではAMP対応した提供元記事はまだ限られるものの、外部フィードから送られてくる記事については様々なHTMLタグがあるため、当初大量のエラーにぶつかってしまいました。
対応としてはAMPタグ置換用のクラスを用意し、ひたすらValidatorとにらめっこしながら正規表現を駆使して作業していったという感じです。

なおAMPのエラーチェックとしてURL末尾に「#development=1」をつけると、ブラウザのConsoleにてエラーログを確認できます。
ただGoogle Chromeを使用されているのであれば、Chromeの拡張機能として「AMP Validator」を入れれば先ほどのハッシュを付けずとも、下の画像のようにエラーログを表示してくれます。

AMP-Validator

3. 構造化データ用意

検索結果の「トップニュース」にAMPリンクを表示させるには、構造化データを正しく実装する必要があります。
Yomerumoの場合は以下のように入れております。

4. Analytics

アナリティクスのタグを埋めることによってどのページにアクセスが来たのか測定できます。
アナリティクスのタグもAMPではカスタムタグに変えないといけません。
ドキュメントにもありますが、新たにプロパティを作成して、既存のレポートと分けるのがよいと思います。
Yomerumoでは現状PV測定に特化して、シンプルにまとめてあります。

その他にもイベント設定も可能ですので詳しくはドキュメントを参照ください。

インデックスされているか確認

AMPはGoogle Search Consoleでページのインデックス状況を確認できます。
反映には少し時間がかかるようでして、Yomerumoの場合AMPページが検索結果「トップニュース」内に表示されるようになっても、Search Consoleに反映するまでには2日ほどかかりました。
(なお「トップニュース」には公開してから3時間足らずで表示確認できました。)

反映されるとインデックスされたページと、エラーが起きているページを表示してくれます。

GS

ちなみにエラーについても同様に、修正してもすぐには反映しませんので、これもまた気長に待ちましょう。

公開してから今のところ

当初AMPについてはJavaScript使用の禁止を始めとして多くの制限があることを知ってたので、デザイン、広告、本サイトの流入減少など様々不安がありました。

ただ公開してからまだ数日ですが、AMPが表示されてから特に本サイトのPVが減少したということはなく、むしろそこからの経由流入もあったりでプラスの面の方を感じています。
おそらくうまくAMPページから本サイトへの導線を作ることが出来れば、AMPも本サイトPV増に貢献してくれるのではないかと思います。

またAMPは<amp-ad>というタグを利用すれば、AMP対応したアドネットワークの広告も入れることが可能です。これによってAMP単体でも収益をもたらせるので、大きくマイナス影響をもたらすことはないのでしょう。

AMP化は一人でもできる?

結論、AMP化は一人でできると思います。
使用タグの制限などルールも多々ありますが、やること自体の難易度は高くありませんでした。
また間違っていたら「ちゃんと」Consoleにエラーが出るので、開発も詰まることはありませんでした。

強いて言えば、私は普段は主にフロント対応なので、その分バックエンド側のコントローラ、タグ置換に時間取ってしまったかもしれません。

ただそれでも一般的なフロントエンジニアであれば問題なく対応できると思います。
何かしらバックエンドを触ることになると思うので、個人的にはコーダーなり、フロントエンジニアが「少し一歩先」に踏み出しくなったときの、ちょうど良い教材になるのではないかなと思います。
(もちろん最後はコードレビュー受けることが大事です!)

以上ざっとですがAMP導入についてでした。

なおYomerumoはAMPに負けず劣らず、高速で記事をサクサク閲覧できるアプリもあります!
iOS
https://itunes.apple.com/jp/app/yomerumo-news-yomerumonyusu/id371083834?mt=8
Android
https://play.google.com/store/apps/details?id=jp.ne.merumo&hl=ja

こちらも何卒よろしくお願いいたします!