Largest Contentful Paint(LCP)の調査方法

原一成氏:さて、Core Web Vitalsの計測の仕方がわかったところで、実際にどう改善していくか見ていきましょう。なお、Core Web Vitalsの指標や計測方法は随時アップデートされており、今日この内容も、すぐに古くなってしまう可能性が高いです。その際には、最新情報を参照してください。

Largest Contentful Paint(LCP)は非常にシンプルで、画面内に表示された最も大きな要素からローディング速度を測る指標です。対象要素は今のところ画像かテキストと考えてよく、大きな画像がある場合にはだいたい画像、ない場合にはテキストになることが多いと考えてよいと思います。

LCPを調査する時のフローとしては、Search Consoleで改善余地のあるURLを見つけて、WebPageTestやDevToolsなどで要素を見つけたり、遅延の原因を特定したりします。

これを改善するためにどういうことをやればよいのかの代表例としては、まずページのレンダリング自体を速くする必要があります。というのも、みなさんも知っているとおり、Webページの表示はサーバーからhtmlを取得して、スタイルやスクリプトの依存を処理して、テキストや画像を表示していきます。仕様でいうと、Time To First ByteやFCPの改善がLCPの改善にもつながってきます。

これはAmebaでとあるページのTime To First Byteをモニタリングしている例ですが、多くのケースではだいたい200ミリセカンド以下で返却されているものの、いくつかのタイミングで、閾値である300ミリセカンドを超えていることがわかりました。CDNを利用しているにもかかわらず、です。

実際にかかった時間を調査してみたところ、CDNでのキャッシュが失効した時に、オリジンサーバーでの取得処理が原因で遅延していることがわかりました。

サーバーでのレスポンス改善にはサーバー内で行われる処理の最適化が有効で、ここにはデータベースやAPIのリクエストも含まれます。また、リダイレクトやネットワーク経路の最適化、CDNを利用して、できるだけ長いキャッシュを指定したり、例えばCDNを利用していても先ほどの例のように遅くなったりすることがあるので、継続的なモニタリングも必要です。

それ以外にも、サーバーからhtmlが返却された後に、ブラウザーでのレンダリングをブロックする要素を最小化することも重要です。長期的なスタイルシートやスクリプト、Webフォントなどが該当します。

LCPが画像に当たる場合には、画像を最適に配信することも重要です。(スライドを指して)右のスクリーンショットはちょっと極端な例ですが、画像の容量が大きかったり、レスポンスが遅かったりする場合には、LCPは大幅に遅延します。

ただし、注意したいことは容量の減らしすぎです。あまりに減らしすぎると、利用体験やコンバージョンに悪影響を与えたりすることがあるので、容量を減らすこと自体が目的にならないように注意をしましょう。さすがにここまで極端に減らすともうわかるので、どこかしらでストップがかかるとは思いますが。

画像のフォーマットを決める際には、避けたほうがよいフォーマットを選択しないようにすることが重要だと思います。例えば、Animation GIFやPathの多いSVG、PNG 24+など、必要以上に容量が大きくなったり、レンダリング時にリソースを過剰に消費したりするようなフォーマットを避けることが1つ言えると思います。

picture要素を使うと、ブラウザーの対応において画像の配信ができるので、品質と容量の両方でメリットがあるかもしれません。もし比較的新しいフォーマットで画像を配信できる場合には、積極的に配信してみてもよいかもしれません。

もし画像のクオリティを選択できる場合には、利用箇所に応じて変化させることもできるでしょう。例えば、拡大などが想定されるイメージギャラリーでは、最高品質の画像を配信して、通常の画像は高品質、リスト内のサムネイルなど優先度がやや低い画像については、低品質の画像を配信するという手もあります。

また、今ではデバイスピクセル密度に応じて画像を配信することが一般的ですが、その際は最大でも2倍にします。かつてスティーブ・ジョブズがRetinaディスプレイの発表時に「およそ2倍より大きい画像は、人の目では区別できない」と言っていたこともありました。ただし、先ほどのイメージギャラリーや画像の拡大が想定される箇所では、例外的にデバイスのピクセル密度に応じて配信してもよいかもしれません。

画像は、htmlやAPIのデータに比べて、変更が少なめなことが多いと思います。容量も大きいこともあり、できるだけ変更を少なくして、長期間ブラウザーやサーバーでキャッシュするとよいでしょう。ファイル名を固有にしたり、httpヘッダーで長いキャッシュを指定したりします。

また、サイト内でよく読み込まれたり、変更が少ない画像であれば、Service Workerでのキャッシュも有効です。あまりに多く保存しすぎると、ディスク容量や処理に影響を及ぼすので、注意が必要です。

Native Lazy−loadingに対応しているブラウザーでは、JavaScriptではなくそちらを使うほうが表示が速くなることもあります。(スライドを指して)これはアメーバブログ(以下、アメブロ)の例ですが、アメブロはJSでの評価に時間がかかっていたので、それをNative Lazy−loadに変更することで、中央値で約1秒の改善が見られました。さらにLCPに当たる画像であれば、遅延読み込みしなくてもよいかもしれません。

Lazy−loadingの例と似ていますが、近年ではJavaScriptで要素をレンダリングすることが多く、画像のリクエストもJavaScriptの読み込みや評価を待たなければならないことも増えてきました。読み込まれる画像があらかじめわかっている場合では、htmlにimage要素を記述したり、プリロードしたりすることで、画像のリクエスト自体を早くすることもできます。

Cumulative Layout Shift(CLS)の調査方法

続いて、Cumulative Layout Shift(CLS)です。CLSは表示の安定性を測る指標で、Layout Shift、つまり表示のガタつきを表します。計測方法は、Viewport内の2フレーム間のレイアウト変更を計測します。

(スライドを指して)例えばこのスクリーンショットの場合、灰色のエリアが下部に移動しています。レイアウトシフトのスコアはimpact fractionとdistance fractionを掛けて算出します。

impact fractionは、画面内でどのぐらいの割合がレイアウトシフトによる影響を受けたかで、この場合、赤い点線が該当します。画面のだいたい75パーセントになります。distance fractionは、実際にどのぐらい移動したかで、灰色の要素は縦方向に画面の25パーセント移動しています。このように算出した値を累積していくのがCLSです。

先日、このCLSの集計方法がアップデートされました。全部を累積していた従来の方法から、ページ内のレイアウトシフトを最大5秒間のセッションに分け、最も値に影響の大きいものだけが計上されるようになりました。

これは、主にページ滞在時間の多いサイト向けの対応です。インフィニティスクロールの1つの例で、以前の方法ではインフィニティスクロールした要素にレイアウトシフトがあった場合には、都度加算されていました。

ただこれは、重大なレイアウトシフトとは言えないこともあり、すべてを加算するよりも、ページ内で最も影響のあったレイアウトシフトを利用したほうがよいのではないかということで変更されました。

CLSをデバッグする時には、WebPageTestやDevToolsを使うのが便利です。テストを実行すると、レイアウトシフトした部分が表示されます。このページでは、マンガのタイトル部分がレイアウトシフトしているようです。

レイアウトシフトの詳細を見ていくと、高さが増えて表示位置が上方向に移動していることがわかりました。これらの情報から、おそらく非同期のAPIリクエストがあって、そこでコンテンツが追加され、その中央揃えの要素のサイズが拡大して、上に移動したと予想できます。

このような非同期でコンテンツをデバッグする場合には、ネットワーク速度を遅くしてみると、目視したい時に便利です。

実際にネットワークを遅くして見てみたところ、テキスト領域にコンテンツが追加されて、レイアウトシフトが起こっているようでした。後述しますが、この場合はプレースホルダとなる要素を表示したりして、事前に高さを確保します。

レイアウトシフトは、本当に軽微なものから大きなものまで、さまざまな箇所で起こります。すべてに対応しようとすると非常に大変です。その時は、最も大きなレイアウトシフトをレポートするようにすると効率的です。完璧に対応するのではなく、影響が大きなものから対応していくことが重要です。

また、レイアウトシフトの原因特定は難しいこともあり、典型的なパターンを覚えることも有効です。

実際、どういうものが典型的なレイアウトシフトなのかというと、そのうちの1つはサイズ未指定の要素です。特に画像やiframeが多いでしょう。

それらはwidth, heightといった、サイズを指定したり、最近ではaspect-ratioというCSSプロパティが普及し始めまたので、こちらでアスペクト比を指定したりすることも有効です。

次に複数サイズの要素です。こちらは入稿コンテンツや広告などによくみられますが、あらかじめ表示領域を確保していたにもかかわらず、レイアウトシフトが起こり得ます。

この場合は、一番大きな領域を確保しておければよいのですが、そうすると不思議な余白が必要になってきたりします。もちろん、解決できるように仕様自体を変更できると好ましいですが、そうでない場合には最低限の高さを確保して、できる限りレイアウトシフトの影響を小さくする手もあります。

こちらも運用コンテンツなど、非同期にリクエストするコンテンツに多い、あったりなかったりのコンテンツです。

その場合には、読み込み中、正常表示、エラー表示、すべてのパターンで同一の表示領域を確保しておく必要があります。

コンポーネント指向のUIライブラリを使っている場合には、アイテムがない場合には何も表示しないようにしている箇所もあると思うので注意です。(スライドを指して)このサンプルコードの場合は、nullを返しているところにプレースホルダやフォールバックの要素が必要でしょう。ただし、あまりにもフォールバックのコンテンツ表示が多いと、問題になることもあるので、やはりその場合にはチームで相談する必要があるでしょう。

デバイスフォントとWebフォントの大きさが大きく異なる場合には、レイアウトシフトを起こす可能性があります。その場合には、Webフォント表示はoptionalにするアプローチもあります。

フォントディスプレイにoptionalを指定すると、Chromeでは100ミリセカンドまでレンダリングを保留し、フォントがダウンロードできた場合はWebフォント表示を、できなかった場合はデバイスフォントを表示します。

なお、フォントの読み込みにpreloadを使う場合には注意が必要です。優先度が上がって読み込みはもちろん早くなりますが、他のリソースに向けた種類をブロックする可能性があるので、そのフォントがページに本当に重要かどうかで都度判断したほうがよいと思います。

プロジェクト内でのCore Web Vitalsの改善の進め方

ここまでCore Web Vitalsの改善方法を簡単に紹介しましたが、実際にプロジェクト内で改善を進めていくためには何が大事になってくるのでしょうか。Amebaでの例をお伝えします。

すでにみなさんも気づいている、もしくは経験されていると思いますが、パフォーマンス改善を進めるためにはチームでの協力、コラボレーションが不可欠です。

例えばCore Web Vitalsの場合、LCPを改善するにはページの情報設計から始まって、画像であれば画像投稿時のフォーマット、圧縮、画像配信時のサーバー管理はどうするかといったような考慮が必要になります。

CLSの場合はより複雑で、運用コンテンツの仕様を変更したり、コンポーネント設計を変更したりしなければならないことも多いでしょう。そもそもパフォーマンス改善に時間を割くためには、チームの協力も必要です。

継続的にパフォーマンスを改善していくには、やはりフローを確立するとよいでしょう。最初に計測環境を整えます。Core Web Vitalsに関しては多くのツールが対応しているので、このステップを早く済ませることができるでしょう。

現在の状況を把握して、チーム内のメンバーへグラフを共有します。この際にはCore Web Vitalsで提示されている閾値を利用すると便利でしょう。「このラインまで減らすのが目標である」というゴールを共有できます。

(スライドを指して)例えばこのAmebaマンガの例では、ゴールまでちょっと時間がかかりそうだ、ということがわかります。

次に、そこから課題を抽出し、改善計画を練ります。Amebaマンガでは、中長期にわたって改善を継続していけるようにメンバーの理解度を上げて、チームとして取り組んでいけるように工夫しました。例えばドキュメントを作成したり、チーム内で計測結果を共有する機会を設けたりしました。この後には個別のパフォーマンス課題を見つけて、それに対しても改善計画を作っていきました。

目標が共有できたら、なぜ改善が大事なのかドキュメントを作成するとよいでしょう。(スライドを指して)これはAmebaで利用しているドキュメントの1つですが、なぜその改善が必要なのか、その際にすべきこと、すべきでないことを記載しています。

また、ドキュメントがあると、仕様策定時やレビューの時に「詳しくはここを見てね」と参照リンクを貼ることもできます。そういった場合に非常に便利です。この例では、チェックリストとして画像の、なぜ画像容量を減らすのか、配信を最適化するのか、CLSの原因とその対策方法などを記載しています。

ある程度改善が見込める実装ができた後には、リリースして効果を検証してみます。その際には、できればABテストを通じて、改善前後の値を検証するようにするのが望ましいと思います。

(スライドを指して)Amebaマンガの場合には、計測環境自体は整えていたので、この図のように改善具合が目に見えてわかりました。変化が見やすかったことも、モチベーション維持に役立ちました。

この例だとリリースしたごとに縦の線がありますが、どんどん減っているのが目に見えてわかったので、改善しているほうも非常にモチベーションを維持できました。

そしてここが非常に大事ですが、もし結果がよかった場合には、チームで祝うことを忘れないようにしましょう。Amebaマンガチームでは、改善グラフの画像と一緒にSlackでお祝い、宣伝しています。少し大げさにお祝いするぐらいでもよいと思います。

ここまで駆け足でCore Web Vitalsの実践編についてお話ししました。今回PWA Nightということで、実際PWAとは直接関係ありませんが、Webアプリケーション自体の品質をよくすること自体がPWAの品質改善にもつながるので、もし参考になれば非常にうれしいです。

本日はありがとうございました。