Chrome DevRel チームが 2023 年に Core Web Vitals のパフォーマンスを向上させる最も効果的な方法であると考えるベスト プラクティスを紹介します。
Google は長年にわたり、ウェブ デベロッパーに対してパフォーマンスを向上させる方法について多くの推奨事項を提供してきました。
それぞれの推奨事項を個別に採用すると、多くのサイトのパフォーマンスを改善できる可能性がありますが、すべての推奨事項に目を向けるのが難しいのはごもっともです。現実的には、1 人のユーザーまたは 1 つのサイトがすべての最適化案に従うことは不可能です。
ウェブ パフォーマンスの仕事でない限り、どの最適化案がサイトに最大の効果をもたらすかは、おそらく簡単にはわかりません。たとえば、重要な CSS を実装すると読み込みのパフォーマンスが向上すると説明した方もいれば、画像を最適化することが重要であるとも耳にしたことがあるでしょう。しかし、両方の作業を行う時間がないとしたら、どうやってどちらを選びますか?
Chrome チームは昨年、「ユーザーのパフォーマンスを向上させるために、開発者に提供できる最も重要な推奨事項は何か」という問いの答えを模索してきました。
この質問に適切に答えるには、特定の推奨事項の技術的なメリットだけでなく、デベロッパーがこれらの推奨事項を実際に採用できる可能性に影響を与える、人的および組織的な要因も考慮する必要があります。つまり、理論上は大きな影響を及ぼす推奨事項があるかもしれませんが、実際には、それらを実装するための時間やリソースを有するサイトはほとんどありません。同様に、重要な推奨事項もありますが、ほとんどのウェブサイトはすでにこれらの手法に即しています。
要するに、ウェブ パフォーマンスで特におすすめの最適化案では、
- 実世界への影響が最も大きい最適化案
- ほとんどのサイトに適している最適化案
- ほとんどのデベロッパーにとって現実的な推奨事項
過去 1 年間、Google は多くの時間を費やしてパフォーマンスに関するすべての最適化案を検証し、上記の 3 つの基準に照らしてそれぞれの最適化案を(質的、定量的に)評価してきました。
この投稿では、Core Web Vitals の各指標のパフォーマンスを向上させるための推奨事項について概説します。ウェブ パフォーマンスを初めて使用する場合や、費用対効果が最も高いものを判断しようとしている場合は、これらの推奨事項から始めることをおすすめします。
Largest Contentful Paint(LCP)
最初の推奨事項は、読み込みパフォーマンスの尺度である Largest Contentful Paint(LCP)です。Core Web Vitals の 3 つの指標のうち、問題があるサイトが最も多いのは LCP です。現在、ウェブ上の全サイトの約半分のみが推奨しきい値を満たしているので、まずはそこから始めましょう。
LCP リソースが HTML ソースから検出可能であることを確認する
HTTP Archive の 2022 Web Almanac によると、モバイルページの 72% に LCP 要素として画像が含まれています。つまり、ほとんどのサイトで LCP を最適化するには、それらの画像を迅速に読み込めるようにする必要があります。
画像の読み込みにかかる時間が課題の一部であることは、多くのデベロッパーにとっては明白でないかもしれません。もう 1 つの重要な要素は、画像の読み込みが開始されるまでの時間です。HTTP Archive データから、多くのサイトが実際にこのタイミングを狙っていることが示唆されます。
実際、LCP 要素が画像であったページのうち 39% には、HTML ドキュメント ソースから検出できないソース URL がありました。つまり、これらの URL は標準の HTML 属性(<img src="...">
や <link rel="preload" href="...">
など)で見つからないため、ブラウザは URL をすぐに検出してすぐに読み込みを開始できます。
画像の読み込みが開始される前に、CSS または JavaScript ファイルのダウンロード、解析、処理が完了するのをページが待たなければならない場合、すでに手遅れになる場合があります。
原則として、LCP 要素が画像の場合、その画像の URL は常に HTML ソースから検出可能である必要があります。これを実現するためのヒントをいくつかご紹介します。
src
属性またはsrcset
属性を持つ<img>
要素を使用して画像を読み込みます。レンダリングに JavaScript を必要とするdata-src
などの標準以外の属性は使用しないでください。使用すると速度が遅くなります。ページの 9% で、LCP 画像がdata-src
の背後に隠れています。クライアントサイド レンダリング(CSR)よりサーバーサイド レンダリング(SSR)を優先します。SSR は、画像を含むページ全体のマークアップが HTML ソースに存在することを示唆するためです。CSR ソリューションでは、画像を検出する前に JavaScript を実行する必要があります。
外部の CSS ファイルまたは JS ファイルから画像を参照する必要がある場合は、
<link rel="preload">
タグを使用して HTML ソースに含めることができます。なお、インライン スタイルで参照される画像は、ブラウザのプリロード スキャナで検出できません。そのため、HTML ソースに画像を見つけても、他のリソースの読み込み時に検出がブロックされる場合があります。このようなケースでは、プリロードが役に立ちます。
LCP イメージの検出可能性に問題があるかどうかを把握できるように、Lighthouse のバージョン 10.0 で新しい監査がリリースされます(2023 年 1 月予定)。
LCP リソースを HTML ソースから検出可能にすると、測定可能な改善につながります。また、次の推奨事項であるリソースを優先する機会も生まれます。
LCP リソースを優先させる
HTML ソースから LCP リソースを検出できることは、LCP リソースの読み込みを早期に開始できるようにするための重要な第一歩ですが、もう 1 つの重要なステップは、そのリソースの読み込みが優先され、多数のあまり重要でないリソースの背後にキューに入れられないようにすることです。
たとえば、標準の <img>
タグを使用して HTML ソースに LCP 画像が含まれている場合でも、ページのドキュメントの <head>
に <img>
タグの前に多数の <script>
タグが含まれている場合、画像リソースの読み込みが開始されるまでに時間がかかることがあります。
この問題を解決する最も簡単な方法は、LCP 画像を読み込む <img>
タグまたは <link>
タグに新しい fetchpriority="high"
属性を設定して、優先度の高いリソースに関するヒントをブラウザに提供することです。これにより、ブラウザはスクリプトの完了を待つのではなく、先にスクリプトを読み込むよう指示します。
Web Almanac によると、対象となるページの 0.03% のみがこの新しい API を利用しています。つまり、ウェブ上のほとんどのサイトでは、わずかな作業で LCP を改善できる余地が十分にあるということです。現在、fetchpriority
属性は Chromium ベースのブラウザでのみサポートされていますが、この API は他のブラウザでは無視される漸進的な拡張機能であるため、デベロッパーには今すぐこれを使用することを強くおすすめします。
Chromium 以外のブラウザの場合、LCP リソースが他のリソースよりも優先されるようにするには、ドキュメントの冒頭で LCP リソースを参照する必要があります。ドキュメントの <head>
に多数の <script>
タグを含むサイトの例では、LCP リソースがこれらのスクリプト リソースよりも優先されるようにするには、スクリプトの前に <link rel="preload">
タグを追加するか、これらのスクリプトを後で <body>
の <img>
の下に移動できます。これは機能しますが、fetchpriority
を使用するよりも人間工学的に劣ります。他のブラウザでも近日中にサポートされる予定です。
LCP リソースの優先順位を決めるもう 1 つの重要な点は、loading="lazy"
属性の追加など、リソースの優先順位の低下を招くようなことは何も行わないようにすることです。現在、実際に 10% のページで LCP 画像に loading="lazy"
が設定されています。すべての画像に遅延読み込み動作を無差別に適用する画像最適化ソリューションに注意してください。この動作をオーバーライドする方法を提供している場合は、必ず LCP 画像に使用してください。どの画像が LCP になるか不明な場合は、ヒューリスティックを使用して妥当な候補を選択してみてください。
重要でないリソースを遅らせることも、LCP リソースの相対的な優先度を効果的に引き上げるもう一つの方法です。たとえば、ユーザー インターフェースの機能を持たないスクリプト(分析スクリプトやソーシャル ウィジェットなど)は、load
イベントが発生するまで延期できるため、ネットワーク帯域幅を奪う他の重要なリソース(LCP リソースなど)と競合することがなくなります。
まとめると、LCP リソースが早期かつ高い優先度で読み込まれるように、以下のベスト プラクティスを実施する必要があります。
- LCP イメージの
<img>
タグにfetchpriority="high"
を追加します。LCP リソースが<link rel="preload">
タグで読み込まれる場合、fetchpriority="high"
も設定できるため、心配はいりません。 - LCP イメージの
<img>
タグではloading="lazy"
を設定しないでください。これを行うと、画像の優先度が下がり、読み込み開始が遅れます。 - 可能であれば、重要性の低いリソースを先送りする。画像をドキュメントの最後に移動するか、画像または iframe にネイティブの遅延読み込みを使用するか、JavaScript を介して非同期で読み込みます。
CDN を使用してドキュメントとリソースの TTFB を最適化する
前の 2 つの推奨事項では、LCP リソースが早期に検出され、すぐに読み込みを開始できるように優先順位を付けることに重点を置いています。このパズルの最後のピースは、最初のドキュメント レスポンスができるだけ迅速に届くようにすることです。
ブラウザは、最初の HTML ドキュメント レスポンスの最初のバイトを受け取るまでサブリソースの読み込みを開始できません。最初のバイトを受け取るのが早ければ、他のあらゆる処理を早く開始できます。
この時間は Time to First Byte(TTFB)と呼ばれ、TTFB を短縮するには以下の方法が最適です。
- できるだけユーザーの地理的に近い場所にコンテンツを提供する
- 最近リクエストしたコンテンツがすぐに再び配信されるように、コンテンツをキャッシュに保存する。
この両方を行うのに最適な方法は、CDN を使用することです。CDN は、世界中に分散しているエッジサーバーにリソースを配信することで、リソースがネットワーク経由でユーザーに到達する距離を制限します。CDN には通常、サイトのニーズに応じてカスタマイズおよび最適化できるきめ細かいキャッシュ制御も用意されています。
多くのデベロッパーは CDN を使用して静的アセットをホストすることに慣れていますが、CDN は動的に生成される HTML ドキュメントも含め、HTML ドキュメントの提供とキャッシュも可能です。
Web Almanac によると、CDN から配信された HTML ドキュメント リクエストの 29% しかありません。これは、サイトがさらなる節約を主張する大きなチャンスがあることを示しています。
CDN を構成する際のヒントをいくつかご紹介します。
- コンテンツをキャッシュに保存する期間を増やすことを検討してください(例: コンテンツが常に最新の状態にすることは実際に重要か?それとも数分前のデータでしょうか?)
- コンテンツを無期限にキャッシュに保存し、更新を行う際はそのキャッシュを削除することも検討してください。
- 送信元サーバーで現在実行中の動的ロジックをエッジ(最新の CDN の機能)に移動できるかどうかを検討する。
一般的に、エッジから直接コンテンツを配信できる(配信元サーバーへのアクセスを回避できる)場合は、パフォーマンスの向上につながります。配信元サーバーまで遡る必要がある場合でも、CDN は一般的にその処理を迅速化するように最適化されているので、どちらにしても有効です。
Cumulative Layout Shift(CLS)
次の推奨事項は、ウェブページの視覚的な安定性の尺度である Cumulative Layout Shift(CLS)です。CLS は 2020 年以降、ウェブで大きく改善されていますが、約 4 分の 1 のウェブサイトはまだ推奨しきい値を満たしていません。そのため、多くのサイトにはユーザー エクスペリエンスを向上させる大きなチャンスが残されています。
ページから読み込まれるすべてのコンテンツに明示的なサイズを設定する
レイアウト シフトは通常、他のコンテンツの読み込みが完了した後に既存のコンテンツが移動した場合に発生します。したがって、このリスクを軽減する主な方法は、必要なスペースをできるだけ前もって確保しておくことです。
サイズが指定されていない画像に起因するレイアウト シフトを修正する最も簡単な方法は、width
属性と height
属性(または同等の CSS プロパティ)を明示的に設定することです。しかしながら、HTTP Archive によると、ページの 72% に、サイズのない画像が 1 つ以上あります。サイズを明示的に指定しないと、ブラウザは初期設定でデフォルトの高さ 0px
を設定し、画像が最終的に読み込まれてサイズが検出されたときにレイアウト シフトが顕著になることがあります。これは、集合的なウェブにとって大きなチャンスであるだけでなく、この記事で紹介している他のおすすめの方法よりもはるかに少ない労力でチャンスを捉えることができます。
また、CLS の原因は画像だけではないことに留意することが重要です。レイアウト シフトは、サードパーティの広告や埋め込み動画など、通常、ページが最初にレンダリングされた後に読み込まれる他のコンテンツが原因で発生することがあります。aspect-ratio
プロパティを使用すると、この問題に対処できます。比較的新しい CSS 機能で、デベロッパーは画像と非画像要素のアスペクト比を明示的に指定できます。これにより、(画面サイズなどに基づいて)動的な width
を設定でき、寸法のある画像の場合とほぼ同じ方法で、ブラウザで適切な高さが自動的に計算されるようになります。
動的コンテンツはその性質上、動的であるため、正確なサイズを把握できない場合があります。ただし、正確なサイズがわからない場合でも、レイアウト シフトの重大度を減らすための対策を講じることはできます。ほとんどの場合、ブラウザが空の要素にデフォルトの高さ 0px
を使用できるようにするよりも、適切な min-height
を設定することをおすすめします。また、min-height
を使用すると、必要に応じてコンテナを最終的なコンテンツの高さまで拡張できるため、通常は簡単に修正できます。ただし、その増加量が最大量から許容可能なレベルまで縮小されただけです。
ページが bfcache の対象となることを確認する
ブラウザは、バックフォワード キャッシュ(略して bfcache)と呼ばれるナビゲーション メカニズムを使用して、前後のページをメモリ スナップショットから直接ブラウザ履歴に瞬時に読み込みます。
bfcache はブラウザレベルでのパフォーマンスの大幅な最適化であり、ページ読み込み中のレイアウト シフトを完全に排除します。多くのサイトでは CLS の大部分がページ読み込みで発生します。bfcache の導入により、2022 年に CLS が大幅に改善しました。
それにもかかわらず、かなりの数のウェブサイトが bfcache の対象とならないため、かなりの数のナビゲーションでウェブ パフォーマンスを無料で向上できるチャンスを逃しています。メモリから復元したくない機密情報がページを読み込む場合を除いて、ページがこの条件を満たしているかどうかを確認することをおすすめします。
サイト所有者は、ページが bfcache の対象となるかどうかを確認し、そうでない場合はなんらかの理由で対処する必要があります。Chrome にはすでに DevTools に bfcache テスターがありますが、今年は、同様のテストを実施する新しい Lighthouse 監査とフィールドでこれを測定するための API を追加してツールを強化する予定です。
CLS セクションに bfcache を含めましたが、これまでで最大の成果が得られたため、bfcache は一般的に他の Core Web Vitals も改善します。ページ ナビゲーションを大幅に改善できる数多くのインスタント ナビゲーションの 1 つです。
レイアウトを誘発する CSS プロパティを使用するアニメーションや遷移を避ける
レイアウト シフトのもう 1 つの一般的な原因は、要素がアニメーション化される場合です。たとえば、上または下からスライドして表示される Cookie バナーやその他の通知バナーが、CLS に影響することがよくあります。これは、これらのバナーによって他のコンテンツが押し出された場合に特に問題になりますが、そうでない場合でもアニメーションが CLS に影響する可能性があります。
HTTP Archive データはアニメーションとレイアウト シフトを結論付けることはできませんが、レイアウトに影響を与える可能性がある CSS プロパティをアニメーション化するページは、「良好」になる可能性が 15% 低いことがわかっています。ページ全体よりも CLS です。一部の宿泊施設は、他の宿泊施設よりも悪い CLS に関連付けられています。たとえば、margin
または border
の幅をアニメーション化するページは「貧しい」になります。CLS は、ページ全体で低と評価される割合の約 2 倍です。
レイアウトを誘導する CSS プロパティを遷移またはアニメーション化するたびにレイアウト シフトが発生し、そのレイアウト シフトがユーザー インタラクションから 500 ミリ秒以内でない場合、CLS に影響するため、これは当然とも言えるでしょう。
一部の開発者は驚くかもしれませんが、要素が通常のドキュメント フローの外側にある場合でもこれが当てはまることです。たとえば、top
や left
をアニメーション化する絶対位置に配置された要素は、他のコンテンツを押し付けていなくても、レイアウト シフトを発生させます。ただし、top
または left
をアニメーション化するのではなく、transform:translateX()
または transform:translateY()
をアニメーション化すると、ブラウザはページ レイアウトを更新せず、レイアウト シフトも発生しません。
パフォーマンスに関するベスト プラクティスとして、ブラウザのコンポジタ スレッドで更新できる CSS プロパティのアニメーションを推奨しています。これは、動作をメインスレッドから GPU に移動させるためです。これは、一般的なパフォーマンスのベスト プラクティスであるだけでなく、CLS の改善にも役立ちます。
原則として、ブラウザでページ レイアウトの更新を要求する CSS プロパティは、アニメーション化または移行しないでください。ただし、ユーザーのタップまたはキーの押下(hover
ではない)に応答して行う場合を除きます。また、可能であれば、CSS の transform
プロパティを使用して、遷移やアニメーションを使用することをおすすめします。
Lighthouse の監査で「合成されていないアニメーションを避ける」を選択すると、ページのアニメーションで動作が遅い可能性のある CSS プロパティが検出されると、警告が表示されます。
First Input Delay(FID)
<ph type="x-smartling-placeholder">最後の推奨事項は、First Input Delay(FID)です。FID は、ユーザー操作に対するページの応答性の尺度です。現在、ウェブ上のほとんどのサイトは FID で非常に高いスコアを得ていますが、Google は過去に FID 指標の欠点を文書化しており、ユーザー操作に対する全体的な応答性を高める余地はまだたくさんあると考えています。
新しい Interaction to Next Paint(INP)指標は FID の後継となる可能性があります。以下の推奨事項はすべて、FID と INP の両方に同様に適用されます。INP ではサイト、特にモバイルでは FID よりもパフォーマンスが悪いため、「良好」にもかかわらず、レスポンシブ デザインに関する推奨事項を真剣に検討することをおすすめします。FID。
長いタスクを避ける、または分割する
タスクは、ブラウザが実行する個別の作業です。タスクには、スクリプトのレンダリング、レイアウト、解析、コンパイル、実行が含まれます。タスクが長時間(50 ミリ秒以上)になると、メインスレッドがユーザー入力に迅速に応答できなくなります。
Web Almanac によると、開発者は長いタスクを回避したり分割したりするために、もっと多くのことをできることを示唆する多くの証拠があります。長いタスクを分割することは、この記事で紹介している他の推奨事項ほど労力は少ないかもしれませんが、この記事で紹介していない他のテクニックよりも労力は少なくて済みます。
JavaScript では処理をできる限り少なくするよう努める必要がありますが、長いタスクを小さなタスクに分割することで、メインスレッドの処理を大幅に減らすことができます。これは、メインスレッドに引き継ぐことを頻繁に行うと、レンダリングの更新やその他のユーザー操作がより迅速に行われるようになります。
また、isInputPending
や Scheduler API などの API を使用する方法もあります。isInputPending
は、ユーザー入力が保留中かどうかを示すブール値を返す関数です。true
が返された場合は、メインスレッドに譲り渡して、保留中のユーザー入力を処理できるようにします。
Scheduler API はより高度なアプローチであり、作業がユーザーに見えるかバックグラウンドで実行されるかを考慮した優先度システムに基づいて作業のスケジュールを設定できます。
長いタスクを分割することで、インタラクションやその結果として生じるレンダリングの更新の処理など、ユーザーが認識する重要な作業にブラウザが適合する機会が増えます。
不要な JavaScript を避ける
間違いありません。ウェブサイトでかつてないほど JavaScript が配布されるようになり、このトレンドがしばらく変わらないようです。JavaScript を配布しすぎると、メインスレッドの注意を奪ってタスクが競合する環境が生まれます。これは、特に重要な起動期間中は、ウェブサイトの応答性に間違いなく影響します。
とはいえ、これは解決できない問題ではありません。次のような選択肢があります。
- Chrome DevTools のカバレッジ ツールを使用して、ウェブサイトのリソース内で使用されていないコードを見つけます。起動時に必要なリソースのサイズを削減することで、ウェブサイトでのコードの解析とコンパイルに要する時間が短縮され、初期のユーザー エクスペリエンスがより滑らかになります。
- カバレッジ ツールを使用して見つかった未使用のコードが「unused」とマークされることがありますこれは、起動時には実行されなかったものの、今後の一部の機能で必要であるためです。このコードは、コード分割によって別のバンドルに移動できます。
- タグ マネージャーを使用している場合は、使用中の場合でも、タグが最適化されているかどうかを定期的にチェックしてください。使用されていないコードを含む古いタグは消去することで、タグ マネージャーの JavaScript のサイズを小さくして効率を高めることができます。
大規模なレンダリング更新を避ける
ウェブサイトの応答性に影響を与えるのは JavaScript だけではありません。レンダリングは、それ自体が負荷の高い作業の一種である可能性があります。レンダリングの大規模な更新が発生すると、ウェブサイトがユーザー入力に応答する能力が妨げられる可能性があります。
レンダリング処理の最適化は簡単なプロセスではなく、多くの場合、何を達成したいかによって異なります。それでも、レンダリングの更新を妥当なものにし、長いタスクにまばらにならないようにするためにできることがいくつかあります。
requestAnimationFrame()
を視覚的でない作業に使用しないでください。requestAnimationFrame()
呼び出しはイベントループのレンダリング フェーズで処理され、このステップで行われる作業が多すぎると、レンダリングの更新が遅延する可能性があります。requestAnimationFrame()
を使用して行う処理は、レンダリングの更新を伴うタスク専用に予約する必要があります。- DOM のサイズを小さくする。DOM のサイズとレイアウト作業の強度には相関関係があります。非常に大きな DOM 向けにレンダラでレイアウトを更新する必要がある場合、レイアウトを再計算するのに必要な作業が大幅に増える可能性があります。
- CSS を含む。CSS の包含は、CSS の
contain
プロパティに依存します。このプロパティは、contain
プロパティが設定されているコンテナのレイアウト処理をブラウザに指示します。レイアウトの範囲を分離して、DOM 内の特定のルートにレンダリングすることもできます。これは必ずしも簡単なプロセスではありませんが、複雑なレイアウトを含む領域を分離することで、不要なレイアウト作業やレンダリング作業を行わずに済みます。
まとめ
ウェブ上には考慮すべきガイダンスが山ほどあることを考えると、ページ パフォーマンスの改善は大変な作業のように思えるかもしれません。ただし、これらの推奨事項に焦点を絞ることで、焦点と目的を持って問題に取り組むことができ、うまくいけばウェブサイトの Core Web Vitals の改善につながります。
ここに示す推奨事項はすべてを網羅しているわけではありませんが、ウェブの状態を慎重に分析した結果、2023 年にサイトが Core Web Vitals のパフォーマンスを向上させる最も効果的な方法であると考えています。
ここに示した推奨事項にさらに踏みたい場合は、以下の最適化ガイドをご覧ください。
新年、そしてすべての人にとってより高速なウェブを実現していきましょう。ユーザーにとって最も重要なあらゆる方法で、サイトが高速になりますように。
写真提供: Devin Avery