every Tech Blog

株式会社エブリーのTech Blogです。

Core Web Vitals 改善のお話

Core Web Vitals改善のお話のタイトル画像

Core Web Vitals 改善のお話

はじめに

こんにちは。MAMADAYS Web 担当の櫻井です。 以前のエブリーエンジニアブログにて Google の Core Web Vitals (以降 CWV) についてご紹介しました。今回は CWV のパフォーマンス改善について、MAMADAYS の Web チームが実際に行ったこと、またその結果についてをご紹介したいと思います。

ゴールとしては CWV の3指標 FID, LCP, CLS を合格基準にすることと、ベンチマークしているサイトよりも優れた数値に改善する*こととしました。

*Google の公式 FAQ によると、CWV が検索ランキングシグナルとして使われるケースは"tie-breaker"の役割が強いようで、ひとまずは競合の中で上位に入り込むことがページパフォーマンスの恩恵を受ける第一歩となります。 - What is the page experience update and how important is it compared to other ranking signals?

まずは計測してみる

パフォーマンス改善においては何よりもまず現状を計測してみることに始まります。今回はひとまず Page Speed Insights(以降 PSI)でサイトの状態を確認してみました。

MAMADAYS のとある記事ページを測定した結果、2021/01 時点では以下のようになりました。

改善前のスコア_17ポイント

なお、結果の見方としては一番上の数字がこの時点で測定した Lab データから算出されるスコアです。直下の「フィールド データ」は現実のユーザの体験をビッグデータとして Google が蓄積したものを反映した数値です。そのため、上のスコアと下のフィールドデータには必ずしも連動しているわけではありません。

CWV は FID, LCP が Good 圏内で、CLS が Bad 圏内。そしてスコアは 17pt。これはベンチマークしているサイトのページと比較してもワースト1位を競う非常に悪いスコアでした。

改善前のベンチマーク別ランキングのグラフ_スコアが17ポイントでワーストを競う

また Web パフォーマンス改善にあたって、FID, LCP, CLS の各数値については改善の結果をリアルタイムで把握したいため、PSI で表示されるフィールドデータではなくラボデータを取得・蓄積すると良いでしょう。前回の記事で紹介したように MAMADAYS ではラボデータを BigQuery に蓄積し metabase でモニタリングするようにしています。ただし、CLS に関しては正しく値を取得できなかったため、特定の記事の Lab データを毎日取得するスクリプトを作成し、モニタリングを行いました。(API は PSI API を使用)

弱点を特定する

CWV の値をある程度把握できたところで、次にどこの改善に着手すべきかを特定します。

MAMADAYS では CWV 合格へ向けて CLS の改善はもちろん、スコアを底上げするために LCP の改善も目指しました。FID はこの時点で最も合格閾値を超過している(100ms)ため、注力しないことを決めました。

具体的な改善アクションを決める際には PSI や Lighthouse が非常に役に立ちます。これらは当該サイトの何がパフォーマンス的に悪いかを親切に文章で教えてくれる機能を有しています。 PSI の結果の画面をスクロールしてみるといくつかの項目で指摘されていました。

  • Remove unused JavaScript

    使用されていない無駄な JavaScript が読み込まれているようです。tree-shaking を適切に行い、デッドコードの除去をする必要があります。また、そもそも使われていない余分なコードをリファクタして削除するなどの整理をすると良さそうです。なお、今回はここの改善は行っていないため説明は割愛しますが、多くの場合ここを改善すれば大きく LCP が下がることが期待できます。 f:id:sa9sha9:20210630144956p:plain

  • Defer offscreen images

    画像の遅延読み込みがされていないようです。ファーストビューに表示されない画像の遅延読み込みをする必要があります。特にsp_footer_banner@3x.png, babyfood_merit_banner@3x.png はファイルサイズが大きく、かつフッター部分に表示される画像なので必ず遅延読み込みをした方が良い画像です。 f:id:sa9sha9:20210630144828p:plain

  • Remove unused CSS

    使用されていない無駄な CSS が読み込まれているようです。 特に viceo-react.css は使用率が 0%で、かなり無駄なロードになってしまっているようです。 f:id:sa9sha9:20210630144848p:plain

  • Eliminate render-blocking resources

    初回レンダリングを遅くする読み込み方法のリソースがあるようです。MAMADAYS では CSS の読み込みが阻害要因となっており、読み込みタイミングの見直しが必要そうです。 f:id:sa9sha9:20210630144832p:plain

  • Properly size images

    画像のサイズが最適でないようです。ここでも一番上の画像については 93%も太っているようなので、適切にサイズを制限する必要がありそうです。 f:id:sa9sha9:20210630144844p:plain

このように PSI で検査するだけで多くの改善ポイントがあることが把握できました。ただし PSI や Lighthouse ではフロントエンドの改善項目しか検査できません。例えば LCP についてはサーバーサイドやインフラの構成を見直すことでも十分に改善できることを念頭においた方がよいでしょう。

LCP の改善

LCP の改善では大きく改善が進んだポイントが3つありました。 LCPの改善のグラフの全容

無駄なリソースの読み込みを除去

1つ目は2月頭の -2000ms ほどの改善です。

1つ目のLCP改善のグラフ_余分なリソース読み込みを抑止し、2000msほど改善に成功

Remove unused CSS」と「Eliminate render-blocking resources」について対応しました。上記の指摘では、カルーセルを実装する slickや、動画プレイヤーのvideo-reactが挙げられています。

Chrome Developer Tool の Coverage 機能で確認すると確かに無駄な CSS であることがわかります。 不要なリソースが読み込まれている図

MAMADAYS では CSS を Next.js の CSS Modules で読み込みをしているため、これらの読み込み箇所を _app.js から実際に必要なコンポーネントに移動しました。これにより不要なCSSの読み込みが除去されたことがわかります。 不要なリソースが読み込まれなくなった図

http2 への切り替え

2つ目は3月頭の -2200ms ほどの改善です。

2つ目のLCP改善のグラフ_画像のレスポンスをhttp2に対応させたことで2200msほど改善に成功

これは Web 内で使われる画像の配信元 CDN のプロトコルを http/1.1 から http/2 へ切り替えたことによるものです。この切り替え設定自体は2月頭に行っていたものですが、このタイミングで PSI がリクエストを http/2 で行うように変更されたため、数値に大きく改善が現れました。

ref: March 3, 2021 | PageSpeed Insights uses http/2 to make network requests

before 画像のレスポンスがhttp/1.1で返ってきている様子

after 画像のレスポンスがhttp/2で返ってくるようになった様子

画像を適切なサイズで配信

3つ目は3月末の -1800ms ほどの改善です。

3つ目のLCP改善のグラフ_読み込み画像のサイズを最適化したことで1800msほどの改善に成功

PSI での指摘項目にあった「Properly size images」に対応した結果でした。MAMADAYS では画像を CloudFront で配信しており、同時に Lambda Edge にてリサイズを行なっています。取得する画像の URL クエリパラメータに?w=400などサイズを指定することでリサイズできるようにしているため、これを使ってサイズの最適化を行いました。

以下はコードの抜粋ですが、sourcemedia attributeで sp/pc 時の画像サイズを適切に切り分けました。Retina 対応のために 2x 時の指定もsrcset attributeで行うと良いでしょう。

また、リサイズと同時に画像タイプも WebP に変換することでよりサイズの軽量化を行なっています。

const spSize = [imgSize.sp, imgSize.sp * 2];
const pcSize = [imgSize.pc, imgSize.pc * 2];

<source
  type='image/webp'
  media='(max-width: 767px)'
  srcSet={`${src}?w=${spSize[0]}&fm=webp, ${src}?w=${spSize[1]}&fm=webp 2x`}
/>
<source
  type='image/webp'
  media='(min-width: 768px)'
  srcSet={`${src}?w=${pcSize[0]}&fm=webp, ${src}?w=${pcSize[1]}&fm=webp 2x`}
/>
<source type='image/webp' srcSet={`${src}?w=${pcSize[0]}&fm=webp, ${src}?w=${pcSize[1]}&fm=webp 2x`} />
<img
  src={`${src}?w=${pcSize[0]}&fm=jpg`}
  alt={alt}
  loading={loading}
  {...(hasSize ? { height, width } : null)}
  className={classnames(css.image, className)}
/>

改善したものの数値に影響がなかったもの

PSI の指摘項目のうち、数値に影響があまり現れないものもあります。 例えば「Defer offscreen images」は 確かに対応した方が良いものですが多くの場合、遅延読み込みするべき画像はファーストビュー外の画像になるため、LCP の対象になるものが少ないです。そのため効果があまり現れなかったのでしょう。この辺りは改善コストを省みて実施するかを判断するのがよいでしょう。

巨人の肩に乗る(大切)

MAMADAYS Web は React 製で、フレームワークに Next.js を使用しています。Next.js はパフォーマンス観点の積極的な改善を行っており、v10.1 ではバンドルサイズが 58%も縮小されたことで純粋にロードするファイルサイズが小さくなり、LCP の向上につながります。このようにコミッティーの勢いがあり積極的に改善が行われているフレームワーク・ライブラリを選定することもパフォーマンス改善において重要になるでしょう。

CLS の改善

CLS の改善では主に画像の領域確保と広告の領域確保を行いました。 CLSの改善のグラフの全容

3月末の時点で画像のサイズ最適化と同時に width と height を指定して領域の確保を行いました。これにより 20%ほどの改善ができました。

その後に数値が大きく上ぶれてしまっているのですが、これは新機能として CLS と相性の悪い機能を実装したことによるものです。これについてはその後改善を行ったり、CLS の算出アルゴリズムが変わったことで元の水準まで戻していますが、新機能を実装する際には Web パフォーマンスの観点からも慎重に検討を行いたいところです。

CLS の算出アルゴリズムが変わったことで CLS が向上

2021/06 に Lighthouse8 がリリースされました。これを機に CLS の算出アルゴリズムが変更になりました。元々は CLS はページ滞在中全てのレイアウトシフトを累計したものになっていましたが、変更後は 5 秒間の内に発生したレイアウトシフト群の合計の中で最も値の大きいもの、というようになりました。これにより多くのサイトで CLS が改善し、MAMADAYS もその恩恵を受けることができました。詳細については以下をご参照ください。

https://web.dev/cls/#what-is-cls

スコアロジックにも変更あり

また Lighthouse8 ではスコアロジックが変わりました。各指標のスコアに反映される重み付けが変更になったのですが、以下のようになりました。 特に CLS が3倍になっているため、従前よりもレイアウトシフトを起こさない実装を心がける必要があります。

指標 従前 → 変更後
First Contentful Paint 15% → 10%
Speed Index 15% → 10%
Largest Contentful Paint 25% → 25%
Time to Interactive 15% → 10%
Total Blocking Time 25% → 30%
Cumulative Layout Shift 5% → 15%

https://web.dev/performance-scoring/

改善の結果

この時点での PSI を測定してみると以下のようになりました。 フィールドデータは遅れて徐々に反映されるため、変化がないように見え少々分かりにくいですが、特に LCP の改善が効いたことで 20pt ほどスコアが向上しました。 改善後のスコア_37ポイント

これによってベンチマークしているサイトの中でもランキング上位を推移するようになりました。 改善後のベンチマーク別ランキングのグラフ_スコアが32~35ポイントで上位を推移するようになりました

今回はランキング上位に入ることはできましたが、CWV の合格基準に達することはかないませんでした。合格基準を満たせるように、MAMADAYSでは今後も改善を重ねていきます。

まとめ

今回はほとんどがフロントエンドにフォーカスした改善でしたが、より改善を進めるためにはサーバーサイドアプリケーションの改善やキャッシュの改善を行う必要があります。MAMADAYS では今後も継続的によりよい UX を提供するためパフォーマンスの改善を続けていきます。よい UX を作ることやパフォーマンスの改善に興味がある方・造詣が深い方はぜひ RECRUIT | every, Inc. までご連絡ください。