Lighthouse の「Avoid Chaining Critical Requests」を修正する方法

Arjen Karel Core Web Vitals Consultant
Arjen Karel
linkedin

「Avoid Chaining Critical Requests」の概要

クリティカルリクエストとは、ブラウザが高い優先度でフェッチするネットワークリクエストのことです。

ページまたはスクリプトが複数のリソースを高い優先度でダウンロードさせる場合、それをクリティカルリクエストチェーンと呼びます。

ブラウザは、これらのすべてのクリティカルリソースがダウンロードされるまで、ページのレンダリングとペイントを(完全に)開始しません。そのため、クリティカルリソースはページの最初のレンダリングをブロックする可能性があります。クリティカルリクエストチェーンが大きくまたは重くなるほど、Lighthouse によるページの読み込み時間への影響が大きくなります。

Critical request chain example

ダウンロード優先度の決定方法

クリティカルリクエストとは、最初のページ読み込み時に高い優先度でダウンロードされるリソースのことです。この優先度はどのように決定されるのでしょうか?

ダウンロード優先度はブラウザ自体が決定します。ブラウザは一連のルールに従って各アセットの優先度を決定します。最終的にどの要素が最も高い優先度を受けるかは、ページの構造によって異なります。ブラウザがページの最初のレンダリングに必要だと判断した要素には、最も高い優先度が与えられます。

ブラウザは最初に、どの要素が最も重要かについての推定を行います。一般的に、ダウンロード優先度は次のように機能します:HTML は常に最も高い優先度を持ち、次にスタイルシート、同期 JavaScript、フォント、Ajax リクエスト、ページ上部の画像、ページ下部の画像、そして非同期 JavaScript の順になります。

自分のページでどのソースに高い優先度が与えられているかを確認できます。Ctrl + Shift + J でデベロッパーコンソールを開きます。ネットワークタブに移動し、列名を右クリックして「Priority」を選択します。

Dev Console Resouce Priority

クリティカルリクエストチェーンはページの読み込み時間にどのように影響するか?

ページを読み込む際、ブラウザは「表示ブロッキング」モードで開始します。このモードでは、最も重要なソースが高い優先度でダウンロードされます。これがクリティカルリソースです。

ブラウザは、すべてのクリティカルリソースがダウンロードされるまで、ページのレンダリングを(完全に)開始しません。そのため、クリティカルリソースはページの最初のレンダリングをブロックする可能性があります。

ページのクリティカルリソースが少ないほど、ブラウザが最初のコンテンツを画面に表示するために行う作業が少なくなり、CPU やその他のリソースの競合も少なくなります。

Lighthouse で「Avoid Chaining Critical Requests」を修正する方法

クリティカルリクエストの影響を軽減するには、3つの方法があります:

  1. クリティカルリソースの数を減らす。クリティカルリソースを削除または遅延させることで、非クリティカルリソースに変換します。
  2. クリティカルバイト数を減らす。明らかなことかもしれませんが、クリティカルパスリソースのバイト数を減らすことで、クリティカルリソースのダウンロードが速くなります。たとえば、gzip 圧縮、JavaScript のツリーシェイキング、画像の最適化、フォントのサブセット化などがあります。
  3. クリティカルパスのダウンロード順序を改善する。プリロードなどのリソースヒントを使用して、リソースの検出をスキップし、クリティカルリソースができるだけ早くダウンロードされるようにします。

多くの選択肢があります。どの選択肢が最適かは、リソースのファイルタイプによって異なります:

1. HTML

HTML(実際に訪問しているページ)は、常に最も高い優先度でダウンロードされます。ページ自体は常にクリティカルリクエストチェーンの一部です。そのため、クリティカルリクエストチェーンを最適化する際にまず考慮すべきはページ自体です。

コンテンツの遅延読み込み: Google をはじめとする多くの大規模サイトでは、クリティカルリクエストチェーンを削減するためにこの手法を使用しています。たとえば検索結果ページでは、すぐには必要のないコンテンツの一部が、後から AJAX リクエストを通じて読み込まれます。

ミニファイ: 小さいほど常に高速です。HTML のミニファイを使用してページからコメント、スペース、空白行を削除します。

圧縮:最後に、スタイルシートを Brotli または GZIP 圧縮で適切に圧縮することが重要です。

2. スタイルシート

ページの head 内のスタイルシートは常にクリティカルです。スタイルなしでは、ブラウザはページがどのように見えるかを知ることができません。そのため、スタイルシートは Lighthouse のクリティカルリクエストチェーンの標準的な構成要素です。

Critical CSS:スタイルシートをリソースヒントによってプリロードし、プリロード完了後にスタイルシートとして追加するというシンプルなトリックで、スタイルシートを非クリティカルにすることができます。
次のコードをページに追加します:ブラウザはスタイルシートをより低い優先度でダウンロードし、CSS をレンダリングブロッキングでないものとして扱います。CSS を待たずにレンダリングを開始します。

<link rel="preload"
      href="css.css"
      type="text/css"
      as="style"
      onload="this.onload=null;this.rel='stylesheet';"/>

ページで何か奇妙なことが起こるのに気づくでしょう。まずページが表示され、CSS の読み込み後にのみスタイリングが適用されます。すべてのコンテンツがスタイルなしの状態からスタイル付きの状態にフラッシュします。これは Critical CSS で修正できます。
Critical CSS はページの表示部分に必要なすべての CSS ルールのコレクションです。Critical CSS は NodeJS または多くのオンラインツールで生成できます。この Critical CSS をページの head に配置し、残りの CSS をより低い優先度で読み込みます。

メディアクエリ:デバイスに合ったスタイルのみを読み込みます。ページはモバイルで訪問されることが多いため、デスクトップやプリント用のスタイルを実際にダウンロードする必要はありません。これにより時間が節約され、Lighthouse のクリティカルリクエストチェーンが短縮されます。

media 属性を使用します。media 属性は、ホームのメディアが現在使用しているメディアと一致しない場合にのみスタイルがダウンロードされるようにします。

<link href="all.css" rel="stylesheet" media="all">
<link href="print.css" rel="stylesheet" media="print">
<link href="desktop.css" rel="stylesheet" media="screen and (min-device-width: 1024px)">

ミニファイ未使用の CSS を削除します。多くのサイトでは Bootstrap などの CSS ライブラリを使用しています。これらのライブラリは多くの場合、過剰に完備されており、すべてのスタイル宣言が使用されているわけではありません。
CSS プリプロセッサ(SASS など)を使用してこれらのライブラリを簡単に編集できます。含めるべきものを変更して未使用のスタイルグループを削除するだけで、大幅に小さくできます。これらのプリプロセッサは、すべてのスペースと改行を削除して CSS をミニファイするオプションも提供します。

圧縮:最後に、スタイルシートを Brotli または GZIP 圧縮で適切に圧縮することが重要です。

3. JavaScript

ページの head 内の JavaScript ファイルは、デフォルトで高い優先度でダウンロードされ、ダウンロードと実行中にページのレンダリングをブロックします。そのため、JavaScript はクリティカルリクエストチェーンの標準的な構成要素です。

Defer と Asyncasync または defer 属性を使用して JavaScript ファイルを非同期に読み込むことで、JavaScript ファイルの優先度を調整します。非同期スクリプトファイルはより低い優先度で並列にダウンロードされます。遅延 JavaScript も並列で読み込まれ、JavaScript の実行が遅延されるため、JavaScript の実行もページの初期読み込みをブロックしません。

// 読み込みと実行をブロック
<script src="normalscript.js">
// async は読み込み中はブロックしないが、実行中はブロックする
<script async src="asyncscript.js">
// defer は読み込み中も実行中もブロックしない
<script defer src="deferscript.js">

コード分割とプリロード:ページが JavaScript の非同期読み込みを許可しない場合、JavaScript を複数のファイルに分割するのが良い方法かもしれません。ページ読み込み時にクリティカルな JavaScript の部分を小さなファイルに配置し、このファイルをプリロードします。非クリティカルな JavaScript を別のファイルに配置し、defer または async で読み込みと実行を行わせます。

ミニファイ:JavaScript Uglifier ツールを使用して、2つの方法でバイト数を削減します。これは JavaScript を分析し、可能な限り小さくするスマートなツールです。

圧縮:さらに、Gzip または Brotli で JavaScript を圧縮してバイト数を削減します。

4. Web フォント

Web フォントは通常、クリティカルリクエストチェーンの中で最後に読み込まれるファイルです。これは、Web フォントが検出に依存しているためです。ブラウザが必要だと判明した時にのみ読み込まれます。そのために、ブラウザはまず HTML を分析し、スタイルシートでどのフォントが使用されているかを調べる必要があります。

プリロード:フォントを使用することが確実な場合、通常はこのフォントをプリロードする方が高速です。フォントはできるだけ早くダウンロードされ、クリティカルリクエストチェーンへの影響が最小限に抑えられます。ページの head にできるだけ早く次のコードを追加して、フォントをプリロードします。

<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
フォント戦略:さらに、フォントの読み込みを高速化する他の方法も多数あります。
  • 常にローカルの Web フォントに依存し、Google Fonts のようなリモートホストされたフォントは使用しないでください。
  • フォントサブセット化でフォントサイズを縮小します。
  • JavaScript の <a href="https://developer.mozilla.org/en-US/docs/Web/API/FontFace">FontFace インターフェース</a>を通じて非クリティカルなフォントを読み込みます。
  • display = swap を使用して、フォントが初期レンダリングをブロックしないようにします。
  • フォントシンセシスを通じて、ブラウザに独自のフォントバリアントを生成させます。

画像

ページ読み込み時に表示可能なビューポートに表示される画像にも高い優先度が与えられ、クリティカルパスに干渉する可能性があります。画像が常にウェブサイトの表示部分に表示されることが確実な場合、この画像もプリロードすることが有用です。

<link rel="preload" as="image" href="important-image.webp">

すぐには表示されないすべての画像については、慎重を期してこれらの画像を遅延読み込みします。loading = "lazy" を使用して、画像が表示される直前まで画像の読み込みを遅延させます。

<img loading="lazy" src="lazy-image.webp" width="20" height="20" alt="...">

5. AJAX リクエスト

AJAX リクエストには常に高い優先度が割り当てられます。そのため、ページのレンダリングが完了するまで AJAX リクエストを延期することが望ましいです。ページが「load」イベントを送信するまで待ちます。

AJAX リクエストを延期できない場合は、プリロードして AJAX リクエストをブラウザで利用可能にすることができます。

window.addEventListener('load', (event)=>{
  console.log('this is a good time for an AJAX request');
});

6. iframe

iframe は通常、高い優先度でダウンロードされます。iframe は実質的にページ内のページであるため、iframe はページの読み込み時間に非常に大きな遅延を引き起こす可能性があります。iframe が必要とするリソースも高い優先度でダウンロードされ、独自のクリティカルリクエストチェーンを形成する場合があります。そのため、iframe の使用は Lighthouse スコアに大きな影響を与える可能性があります。

loading = "lazy" 属性を使用して iframe の読み込みを遅延させることができます。これは、読み込み時に iframe がすぐに表示されない場合に効果的です。JavaScript を通じて iframe をページに注入する方が速いことが多いです。これにより、タイミングをより制御でき、クリティカルリクエストチェーンに含まれないようにすることができます。

Lab data is not enough.

I analyze your field data to find the edge cases failing your user experience.

Analyze My Data >>

  • Real User Data
  • Edge Case Detection
  • UX Focused
Lighthouse の「Avoid Chaining Critical Requests」を修正する方法 Core Web Vitals Lighthouse の「Avoid Chaining Critical Requests」を修正する方法