ウェブ コミュニティは長年にわたり、ウェブ パフォーマンスの最適化に関する豊富な知識を蓄積してきました。1 つの最適化で多くのサイトのパフォーマンスを改善できる一方で、すべての最適化を一度に行うことは負担になる可能性があります。また、実際には、特定のサイトに適用できる最適化は一部に限られます。
ウェブ パフォーマンスが専門でない限り、サイトに最も大きな影響を与える最適化は明らかではないかもしれません。すべての最適化を実施する時間はおそらくないでしょう。そのため、ユーザーのパフォーマンスを改善するために、最も効果的な最適化はどれかを自問することが重要です。
パフォーマンスの最適化について、技術的なメリットのみで判断することはできません。また、特定の最適化を実施できる可能性に影響する人的要因と組織的要因も考慮する必要があります。理論上はパフォーマンスの大幅な向上につながる改善でも、実際には実装する時間やリソースがないデベロッパーがほとんどです。一方で、ほとんどの企業がすでに実践している、パフォーマンスに大きな影響を与えるベスト プラクティスもあります。このガイドでは、次のようなウェブ パフォーマンスの最適化について説明します。
- 実世界への影響が最も大きい
- ほとんどのサイトに関連し、適用できる
- ほとんどのデベロッパーが実装できる
これらを組み合わせることで、Core Web Vitals 指標を改善するための最も現実的で効果的な方法を実現できます。ウェブ パフォーマンスを初めて学ぶ場合や、投資収益率を最大化できる方法をまだ決めていない場合は、まずこのページをご覧ください。
Interaction to Next Paint(INP)
最新の Core Web Vitals 指標である Interaction to Next Paint(INP)は、改善の余地が最も大きい指標の一つです。ただし、非推奨となった前任者と比較して、「良好」なエクスペリエンスのしきい値を満たしているサイトは大幅に減少しているため、インタラクションの応答性を最適化する方法を初めて学ぶデベロッパーも少なくないかもしれません。最初に、インプレッション数を最も効果的に増やすための必須テクニックをご確認ください。
1. 長いタスクを分割するために頻繁に Yield する
タスクとは、レンダリング、レイアウト、解析、コンパイル、スクリプトの実行など、ブラウザが行う個別の作業のことです。タスクの所要時間が 50 ミリ秒を超えると、長時間タスクになります。長いタスクは、メインスレッドがユーザー操作にすばやく応答できなくなる可能性があるため、問題になります。
JavaScript では常に、できるだけ少ない処理を行うようにする必要がありますが、長いタスクを分割することで、メインスレッドをサポートできます。これは、メインスレッドに頻繁に譲渡することで実現できます。これにより、レンダリングの更新やその他のユーザー操作をより早く行うことができます。
Scheduler API を使用すると、優先度システムを使用してタスクをキューに追加できます。具体的には、scheduler.yield() API は長いタスクを分割し、タスクキュー内の位置を放棄することなくインタラクションを処理できるようにします。
長いタスクを分割することで、ブラウザがユーザーの操作を妨げる重要な作業を実行する機会を増やすことができます。
2. 不要な JavaScript を避ける
ウェブサイトはかつてないほど多くの JavaScript を配信しています。この傾向は変わっていないようです。送信する JavaScript が多すぎると、タスクがメインスレッドの注意を奪い合う環境が生まれます。これは、特に重要な起動時にウェブサイトの応答性に影響する可能性があります。
ただし、これは解決できない問題ではなく、次の方法があります。
- 冗長な JavaScript ベースの実装ではなく、広く利用可能なウェブ プラットフォームの機能のベースラインを使用します。
- Chrome DevTools のカバレッジ ツールを使用して、スクリプト内の未使用のコードを探します。起動時に必要なリソースのサイズを小さくすることで、ページがコードの解析とコンパイルに費やす時間を短縮し、スムーズな初期ユーザー エクスペリエンスを提供できます。
- コード分割を使用して、初期レンダリングには必要ないものの、後で使用されるコード用に個別のバンドルを作成します。
- タグ マネージャーを使用している場合は、定期的にタグを最適化してください。使用されていないコードを含む古いタグを削除すると、タグ マネージャーの JavaScript のフットプリントを削減できます。
3. レンダリングの大きな更新を回避する
JavaScript の実行は、ウェブサイトの応答性に影響する要素の 1 つにすぎません。レンダリングは、それ自体が費用のかかる作業です。大規模なレンダリングの更新中は、ウェブサイトがユーザー操作にさらに遅く応答する可能性があります。
レンダリング作業の最適化は簡単なプロセスではなく、何を達成しようとしているかによって異なります。それでも、レンダリング タスクが長時間タスクにならないようにするために、次のことを行えます。
- JavaScript コードで DOM の読み取りと書き込みを再編成して、強制レイアウトとレイアウト スラッシングを回避します。
- DOM サイズを小さくする。DOM のサイズとレイアウト作業の負荷は相関しています。レンダラが非常に大きな DOM のレイアウトを更新する必要がある場合、レイアウトの再計算に必要な作業が大幅に増加する可能性があります。
- CSS の制限を使用すると、画面外の DOM コンテンツを遅延レンダリングできます。必ずしも簡単ではありませんが、複雑なレイアウトを含む領域を分離することで、不要なレイアウトとレンダリングの作業を回避できます。
Largest Contentful Paint(LCP)
Largest Contentful Paint(LCP)は、デベロッパーが最も苦労する Core Web Vitals です。Chrome UX レポートのサイトの40% は、優れたユーザー エクスペリエンスに必要な 推奨される LCP のしきい値を満たしていません。Chrome チームは、LCP を改善するための最も効果的な方法として、次の手法を推奨しています。
1. LCP リソースが HTML ソースから検出可能で、優先度が設定されていることを確認する
Chrome チームは、ウェブでの LCP に関して次のことを確認しています。
- HTTP Archive の 2024 年ウェブ アルマナックによると、モバイル ページの 73% で、LCP 要素として画像が使用されています。
- Chrome の実際のユーザーデータの分析によると、LCP が遅いオリジンのほとんどは、LCP 画像のダウンロードに p75 LCP 時間の10%未満しか費やしていません。
- LCP が低いページでは、LCP 画像の読み込みがクライアントで 75 パーセンタイルあたり 1,290 ミリ秒遅れています。これは、高速なエクスペリエンスのための予算の半分以上です。
- LCP 要素が画像であるページのうち、画像の 35% は、最初の HTML レスポンスで検出できないソース URL(
<img src="...">
や<link rel="preload" href="...">
など)を持っていました。これらの URL は、ブラウザのプリロード スキャナによってできるだけ早く検出できます。 - Web Almanac によると、対象となるページの15% が
fetchpriority
HTML 属性を利用して、リソースに優先度を設定しています。これには、比較的少ない労力でページの LCP を改善できるリソースも含まれます。
これらの統計情報は、デベロッパーが LCP 画像のリソース読み込み遅延とリソース読み込み時間の両方を削減できる大きな機会があることを示しています。
リソースの読み込み遅延が問題となっている場合は、画像の読み込みを開始する前に CSS または JavaScript が完全に読み込まれるのを待つ必要がある場合、LCP を改善するにはすでに遅すぎる可能性があることを覚えておくことが重要です。さらに、fetchpriority
HTML 属性を使用して優先順位を変更し、より多くの帯域幅を受け取るようにすることで、LCP 画像のリソースの読み込み時間を短縮できます。これにより、読み込みが速くなります。
LCP 要素が画像の場合は、リソースの読み込み遅延を短縮するために、画像の URL が HTML レスポンスで検出可能である必要があります。そのためには、次のようなことをおすすめします。
src
属性またはsrcset
属性を持つ<img>
要素を使用して画像を読み込みます。レンダリングに JavaScript を必要とするdata-src
などの標準以外の属性は使用しないでください。レンダリングに時間がかかります。7% のページで、LCP 画像がdata-src
の背後に隠れています。- クライアントサイド レンダリング(CSR)よりもサーバーサイド レンダリング(SSR)を優先する。SSR では、ページ全体のマークアップ(画像を含む)が HTML ソースに存在することを前提としています。CSR ソリューションでは、画像を検出するには JavaScript を実行する必要があります。
- 画像を外部 CSS ファイルまたは JS ファイルから参照する必要がある場合でも、
<link rel="preload">
タグを使用して HTML ソースに含めることができます。インライン スタイルで参照される画像は、ブラウザのプリロード スキャナでは検出されないことに注意してください。そのため、HTML ソースに画像が含まれていても、他のリソースの読み込み中に画像の検出がブロックされることがあります。このような場合は、プリロードが役に立ちます。
さらに、LCP リソースを早期に優先度高く読み込むことで、リソースの読み込み時間を短縮できます。
- LCP 画像の
<img>
タグまたは<link rel="preload">
タグにfetchpriority="high"
属性を追加します。これにより、画像リソースの優先度が上がり、より早く読み込みを開始できるようになります。 - LCP 画像の
<img>
タグからloading="lazy"
属性を削除します。これにより、画像がビューポート内またはビューポートの近くに表示されていることを確認する際に発生する読み込み遅延を回避できます。 - 可能であれば、重要でないリソースを延期します。これらのリソースをドキュメントの最後尾に移動したり、画像や iframe を遅延読み込みしたり、JavaScript を使用して非同期で読み込んだりすることで、LCP 画像などのより重要なリソースをより速く読み込めるようになります。
2. 即時ナビゲーションを目標とする
ページの読み込みを待たずに済むのが理想的なユーザー エクスペリエンスです。リソースの検出や優先順位付けなどの LCP の最適化は、LCP 要素の読み込みとレンダリングを待つユーザーの時間を短縮するのに効果的ですが、ネットワーク経由でバイトが読み込まれ、ページにレンダリングされるまでの時間には物理的な限界があります。その上限に達するずっと前に、数ミリ秒でも短縮するには、非常に大きな労力が必要になります。そのため、即時ナビゲーションを実現するには、まったく異なるアプローチをとる必要があります。
即時ナビゲーションでは、ユーザーがページに移動する前に、そのページの読み込みとレンダリングが試行されます。これにより、事前レンダリングされたページをすぐに表示でき、LCP をほぼゼロに抑えることができます。復元と推測の 2 つの方法があります。ユーザーが以前にアクセスしたページに前後に移動すると、そのページはメモリ内キャッシュからすばやく復元され、ユーザーが離れたときとまったく同じ状態で表示されます。ウェブ アプリケーションでは、ユーザーが次に移動するページを予測することもできます。予測が正しければ、ユーザーが移動するまでに次のページが読み込まれ、レンダリングされます。
以前にアクセスしたページを復元できるのは、バックフォワード キャッシュ(bfcache)があるからです。使用するには、ページが bfcache の利用条件を満たしていることを確認する必要があります。ページが bfcache の対象にならない一般的な理由は、no-store
キャッシュ ディレクティブで提供されているか、unload
イベント リスナーが設定されているためです。
完全にレンダリングされたページを復元すると、読み込みのパフォーマンスだけでなく、レイアウトの安定性も向上します。bfcache と CLS の改善効果について詳しくは、ページが bfcache の対象となるようにするをご覧ください。
Browser Support
ユーザーがアクセスする次のページをプリレンダリングすることも、LCP のパフォーマンスを大幅に改善する効果的な方法です。これは Speculation Rules API によって実現できます。ただし、これらのメリットを実現するには、正しいページがプリレンダリングされていることを確認してください。不正確な推測は、サーバー側とクライアント側の両方でリソースを浪費し、パフォーマンスに悪影響を及ぼす可能性があります。そのため、次のページがどのような内容になるか確信が持てない場合は、そのページのプリレンダリングを控えめにする必要があります。疑問がある場合は、アナリティクス データに基づいて、次にアクセスされる可能性が高いページをより積極的にプリレンダリングできます。
3. CDN を使用して TTFB を最適化する
前回の推奨事項では、ユーザーに最適なエクスペリエンスを提供する即時ナビゲーションに焦点を当てましたが、bfcache と推測読み込み手法が適用できない状況もあります。ユーザーがクロスオリジン リンクからサイトにアクセスし、最初の HTML ドキュメント レスポンスが LCP を効果的にブロックしている場合について考えてみましょう。ブラウザは、レスポンスの最初のバイトを受け取るまでサブリソースの読み込みを開始できません。早ければ早いほど、他の作業も早く始められます。
この時間は、最初のバイトを受け取るまでの時間(TTFB)と呼ばれます。TTFB を短縮するための最善の方法は次のとおりです。
- コンテンツをできるだけユーザーの地理的位置の近くで配信します。
- そのコンテンツをキャッシュに保存し、近い将来に再度リクエストされた場合にすばやく提供できるようにします。
これらの両方を実現する最善の方法は、CDN を使用することです。CDN は、世界中のエッジサーバーにリソースを分散するため、リソースがワイヤーを介してユーザーに到達する距離を制限できます。また、通常 CDN には、サイトのニーズに合わせて調整できるきめ細かいキャッシュ制御機能があります。
CDN は HTML ドキュメントの配信とキャッシュ保存も行えますが、ウェブ アルマナックによると、HTML ドキュメント リクエストの 33% のみが CDN から提供されています。つまり、サイトはさらなる節約を実現できる大きなチャンスがあります。
CDN を構成するためのヒントを次に示します。
- 静的 HTML ドキュメントを短時間でもキャッシュに保存します。たとえば、コンテンツが常に新鮮であることは重要ですか?数分遅れても問題ないですか?
- 配信元サーバーで実行されている動的ロジックをエッジに移動できるかどうかを検討します。これは、ほとんどの最新の CDN の機能です。
エッジから直接コンテンツを提供して、オリジン サーバーにアクセスしなくて済む場合は、パフォーマンスが向上します。オリジンまでリクエストを送信する必要がある場合でも、CDN は通常、より迅速に処理するように最適化されているため、どちらの場合でもメリットがあります。
Cumulative Layout Shift(CLS)
Cumulative Layout Shift(CLS)は、ウェブページの視覚的安定性を測定する指標です。CLS はほとんどのサイトで良好な結果が得られる指標ですが、約 4 分の 1 のサイトが推奨されるしきい値を満たしていないため、多くのサイトでユーザー エクスペリエンスを改善する大きな機会が残されています。
1. ページから読み込まれるコンテンツに明示的なサイズを設定する
レイアウトのずれは、通常、他のコンテンツの読み込みが完了した後に既存のコンテンツが移動したときに発生します。CLS を改善する主な方法は、必要なスペースをできるだけ事前に予約することです。
サイズが指定されていない画像が原因でレイアウトがずれる場合は、width
属性と height
属性、または同等の CSS プロパティを明示的に設定するのが最善の方法です。ページの66% に、サイズが設定されていない画像が 1 つ以上あります。明示的なサイズが指定されていない場合、これらの画像の初期の高さは 0px
になります。このため、画像が読み込まれてブラウザがそのディメンションを検出すると、レイアウトがずれる可能性があります。これは、集合的なウェブにとって大きな機会であり、この機会を活用するために必要な労力は、このガイドで推奨されている他の推奨事項よりも少ないです。
CLS に影響を与えるのは画像だけではありません。レイアウトのずれは、通常はページの初期レンダリング後に読み込まれる他のコンテンツ(サードパーティ広告や埋め込み動画など)が原因で発生することがあります。aspect-ratio
プロパティはこのような場合に役立ちます。これは広く利用可能なベースラインの CSS 機能で、デベロッパーは画像要素だけでなく画像以外の要素にもアスペクト比を明示的に設定できます。これにより、(画面サイズに基づくなど)動的 width
を設定し、寸法のある画像の場合と同様に、ブラウザが適切な高さを自動的に計算できるようになります。
ただし、動的コンテンツの正確なサイズを把握できない場合もあります。正確なサイズがわからない場合でも、レイアウトのずれの重大度を軽減することは可能です。空の要素にブラウザがデフォルトの高さ 0px
を使用するよりも、ほとんどの場合、適切な min-height
を設定することをおすすめします。通常、min-height
を使用すると、必要に応じてコンテナを最終的なコンテンツの高さまで拡大できるため、簡単に修正できます。この場合、コンテナの拡大量は許容できるレベルに抑えられます。
2. ページが bfcache の対象であることを確認する
このガイドの前半で説明したように、バックフォワード キャッシュ(bfcache)は、ブラウザの履歴の前のページまたは後のページをメモリ スナップショットから即座に読み込みます。bfcache は、LCP を改善するブラウザレベルの重要なパフォーマンス最適化ですが、レイアウト シフトも完全に排除します。実際、2022 年の bfcache の導入は、その年の CLS の最大の改善につながりました。
にもかかわらず、多くのウェブサイトは bfcache の対象外であるため、この無料のウェブ パフォーマンス向上のメリットを享受できていません。ページにメモリから復元したくない機密情報が読み込まれる場合を除き、ページが bfcache を使用できる状態であることを確認してください。
サイト所有者は、ページが bfcache の対象かどうかを確認し、対象外である理由を修正する必要があります。Chrome の DevTools には bfcache テスターがあります。また、Not Restored Reasons API を使用して、フィールドで利用条件を満たしていない理由を検出することもできます。
3. レイアウトを誘発する CSS プロパティを使用するアニメーションや遷移は避ける
レイアウトがずれる原因としてよくあるのは、要素がアニメーション化される場合です。たとえば、上部または下部からスライドインする Cookie バナーやその他の通知バナーは、多くの場合 CLS の増加につながります。これは、これらのバナーが他のコンテンツを押しのける場合に特に問題になりますが、押しのけない場合でも、アニメーション化すると CLS に影響する可能性があります。
HTTP Archive のデータでは、アニメーションとレイアウトのずれを明確に結び付けることはできませんが、レイアウトに影響する可能性のある CSS プロパティをアニメーション化するページでは、全体的なページと比較して「良好」な CLS の確率が 15% 低いことがわかります。一部のプロパティは、他のプロパティよりも CLS の低下と関連付けられています。たとえば、margin
または border
の幅をアニメーション化するページでは、CLS が「低い」と評価されるページの割合が、ページ全体が低いと評価される割合のほぼ 2 倍です。
これは、レイアウトを誘発する CSS プロパティをすべて遷移またはアニメーション化すると、レイアウト シフトが発生するため、驚くべきことではありません。これらのレイアウト シフトがユーザー操作から 500 ミリ秒以内に発生した場合、CLS に影響します。
一部のデベロッパーにとって驚くべきことに、これは要素が通常のドキュメント フローから外に出た場合でも同様です。たとえば、top
または left
をアニメーション化する絶対配置要素は、他のコンテンツを押し出していない場合でも、レイアウトのずれを生じさせます。ただし、top
または left
をアニメーション化する代わりに transform:translateX()
または transform:translateY()
をアニメーション化すると、ブラウザがページ レイアウトを更新しないため、レイアウトのずれを回避できます。
ブラウザのコンポジタ スレッドで更新できる CSS プロパティのアニメーションを優先することは、長い間パフォーマンスに関するベスト プラクティスとされてきましたが、これは、その処理をメインスレッドから GPU に移すためです。これは一般的なパフォーマンスのベスト プラクティスであるだけでなく、CLS の改善にも役立ちます。
一般的なルールとして、ユーザーのタップやキー入力(hover
は除く)に応じて行わない限り、ブラウザがページ レイアウトを更新する必要がある CSS プロパティをアニメーション化または遷移させないでください。可能な限り、CSS transform
プロパティを使用して遷移とアニメーションを優先してください。
Lighthouse の監査「合成されていないアニメーションは使用しないでください」は、ページで遅くなる可能性のある CSS プロパティがアニメーション化されている場合に警告します。
まとめ
ウェブ上には、ページのパフォーマンスを高めるためのガイダンスが数多く存在するため、その作業は困難に思えるかもしれません。ただし、最も効果的なベスト プラクティスのリストに集中することで、問題に新たな視点から取り組み、ウェブサイトの Core Web Vitals の改善につながる可能性があります。
ここで紹介した最適化以外にも、以下のガイドで詳細をご確認ください。
付録: 変更ログ
このドキュメントの主要な変更は、上位の推奨事項がいつ、なぜ変更されたかを説明するために、ここで追跡されます。
2024 年 10 月
2024 年の更新:
- INP
- Core Web Vitals 指標として INP がリリースされたことに伴い、この指標は FID から INP に変更され、リストの一番上の指標になりました。
- 長いタスクを分割する際に
isInputPending
API を使用することを推奨していた内容を撤回しました。理由について詳しくは、長時間のタスクを最適化するをご覧ください。
- LCP
- 見つけやすさと優先順位付けの推奨事項を 1 つに統合しました。
- 即時ナビゲーションを実現するための新しい最適化案を追加しました。
2023 年 1 月
推奨事項の初期リストは次のとおりです。
- LCP
- LCP リソースが HTML ソースから検出可能であることを確認する
- LCP リソースが優先されていることを確認する
- CDN を使用してドキュメントとリソースの TTFB を最適化する
- CLS
- ページから読み込まれるコンテンツに明示的なサイズを設定する
- ページが bfcache の対象であることを確認する
- レイアウトを誘発する CSS プロパティを使用するアニメーションや遷移は避ける
- FID
- 長いタスクを回避するか、分割する
- 不要な JavaScript を避ける
- レンダリングの大きな更新を回避する
2023 年の Google I/O プレゼンテーションの動画概要もご覧ください。