loading-sequence
Core Web Vitalsを改善するためのリソース読み込み順序の最適化手法を提供します。重要なリソースの検出・読み込み順序を見直すことでFCP・LCP・FIDを向上させたい場合に活用してください。
description の原文を見る
Teaches resource loading sequence optimization for Core Web Vitals. Use when you need to improve FCP, LCP, or FID by reordering how critical resources are discovered and loaded.
SKILL.md 本文
ローディングシーケンスを最適化する
目次
すべての成功したウェブページロードでは、いくつかの重要なコンポーネントとリソースがちょうど良いタイミングで利用可能になり、スムーズなローディング体験を提供します。これにより、ユーザーはアプリケーションのパフォーマンスが優れていると認識します。この優れたユーザー体験は、一般的に Core Web Vitals に合格することにもつながります。
いつ使うべきか
- Core Web Vitals のページロードパフォーマンス最適化が必要な場合
- 1P JS、3P JS、CSS、フォント、画像のローディングを調整する必要がある場合
- サードパーティスクリプトがローディングパフォーマンスに悪影響を与えている場合
実装方法
- 重要な CSS とフォント CSS はインライン化し、外部フォントに対しては preconnect を使用する
- FCP が LCP より前に、LCP が FID より前に発火するようにリソースを並べる
- ATF 画像よりも前にネットワーク上で 1P JS の取得を開始する
- 重要でないスクリプトには
asyncまたはdefer属性を使用する - 折り返し下の画像と非必須のサードパーティリソースは遅延ロードする
詳細
First Content Paint、Largest Contentful Paint、First Input Delay などのパフォーマンス測定に使用される主要な メトリクス は、重要なリソースのローディングシーケンスに直接依存しています。例えば、ヒーロー画像 のような重要なリソースが読み込まれないと、ページは LCP を発火させることができません。この記事は、リソースのローディングシーケンスと Web Vitals の関係について説明しています。私たちの目標は、Web Vitals を改善するためのローディングシーケンス最適化について明確なガイダンスを提供することです。
理想的なローディングシーケンスを確立する前に、なぜローディングシーケンスを正しく設定することが難しいのかを理解する必要があります。
最適なローディングを実現することが難しい理由
パートナーのウェブサイトに対するパフォーマンス分析の独特な機会に恵まれました。異なるパートナーサイト全体でページの効率的なローディングに悪影響を与える複数の類似した問題を特定しました。
開発者の期待とブラウザのリソース優先順位付けの間に、しばしば大きなギャップが存在します。これは多くの場合、パフォーマンススコアが最適でない結果をもたらします。さらに分析して、このギャップの原因を発見しました。以下の点は分析の本質をまとめたものです。
最適でないシーケンス設定
Web Vitals の最適化には、各メトリクスが何を意味するかの理解だけでなく、発火の順序と異なる重要なリソースとの関係についての理解も必要です。FCP は LCP より前に、LCP は FID より前に発火します。したがって、FCP を達成するために必要なリソースは、LCP に必要なリソースよりも優先され、その後 FID に必要なリソースが優先されるべきです。
リソースはしばしば正しい順序でシーケンス化またはパイプライン化されていません。これは、開発者がメトリクスのリソースロードへの依存性を認識していない可能性があるためです。結果として、関連するリソースがそれぞれのメトリクスをトリガーするための適切なタイミングで利用可能でない場合があります。
例:
a) FCP が発火するまでに、ヒーロー画像が LCP を発火させるために利用可能である必要があります。 b) LCP が発火するまでに、JavaScript (JS) がダウンロード、パース、実行準備完了(またはすでに実行中)してインタラクション (FID) をブロック解除する必要があります。
ネットワーク/CPU 利用率
リソースは CPU とネットワークの完全な利用率を確保するように適切にパイプライン化されていません。これはプロセスがネットワークバウンドの場合の CPU における「デッドタイム」や、その逆をもたらします。
この良い例は、並行してまたは順序立ててダウンロード可能なスクリプトです。並行ダウンロード中に帯域幅が分割されるため、すべてのスクリプトのダウンロード総時間は並行ダウンロードと順序立ったダウンロードの両方で同じです。スクリプトを並行してダウンロードする場合、ダウンロード中に CPU は十分に活用されません。しかし、スクリプトを順序立ててダウンロードする場合、CPU はダウンロード完了後すぐに最初のスクリプトを処理開始できます。これにより、CPU とネットワークの利用率が向上します。
サードパーティ (3P) 製品
3P ライブラリは、ウェブサイトに一般的な機能とカスタマイズ性を追加するためにしばしば必要です。サードパーティには、広告、分析、ソーシャルウィジェット、ライブチャット、ウェブサイトを機能させるその他の埋め込みが含まれます。サードパーティライブラリには、独自の JavaScript、画像、フォントなどが含まれています。
3P 製品は通常、コンシューマーサイトのローディングパフォーマンスを最適化およびサポートするインセンティブを持ちません。これらは JavaScript 実行コストが高く、インタラクティビティを遅延させたり、他の重要なリソースのダウンロードを阻害したりする可能性があります。
3P 製品を含める開発者は、パフォーマンスの影響よりも機能的な価値に焦点を当てがちです。結果として、3P リソースが全体的なローディングシーケンスにどのように適合するかについての完全な検討なしに、無計画に追加されることがあります。これにより、それらを制御およびスケジュール化することが難しくなります。
プラットフォームの癖
ブラウザはリクエストの優先順位付けとヒントの実装方法が異なる場合があります。プラットフォームとその癖について深い知識がある場合、最適化が容易になります。特定のブラウザに特有の動作は、希望するローディングシーケンスを一貫して達成することを難しくします。
その一例が、Chromium プラットフォームの preload バグ です。Preload (<link rel=preload>) 指示は、ブラウザにキーリソースをできるだけ早くダウンロードするように指示するために使用できます。これは、リソースが現在のページで使用されることが確実な場合にのみ使用すべきです。Chromium のバグにより、<link rel=preload> を介して発行されたリクエストが、優先度がより高い場合でも、プリロードスキャナに見られる他のリクエストより前に常に開始される動作が生じます。これのような問題は、最適化計画に支障をきたします。
HTTP2 優先順位付け
プロトコル自体は、リソースの順序と優先度を調整するための多くのオプションやツールを提供しません。より良い優先順位付けプリミティブが利用可能であったとしても、HTTP2 優先順位付けの基礎的な問題があり、最適なシーケンス化を難しくしています。主に、サーバーまたは CDN が個々のリソースのリクエストをどの順序で優先順位付けするかを予測することができません。一部の CDN はリクエストを再優先順位付けし、他は部分的、不完全、または優先順位付けなしで実装しています。
リソースレベルの最適化
効果的なシーケンス化では、シーケンス化されるリソースが最適に機能して迅速にロードされることが必要です。重要な CSS はインライン化され、画像は正しくサイズ設定され、JS はコード分割されて段階的に配信されるべきです。
フレームワーク自体は、コード分割とJS とデータの段階的な配信を可能にする構築体を欠いています。ユーザーは 1P JS の大きなチャンクを分割するために以下のいずれかに頼る必要があります:
- Modern React (Suspense / Concurrent mode / Data Fetching) - これはまだ実験的なみです
- ダイナミックインポートを使用した遅延ロード - これは直感的ではなく、開発者はコード分割する境界を手動で特定する必要があります。
コード分割する場合、粒度とパフォーマンスのトレードオフがあるため、開発者はチャンクの粒度をちょうど良く実現する必要があります。
より高い粒度が望ましいのは、以下の理由です:
- 個々のルートおよび後続のユーザーインタラクションに必要な JS を最小化する
- 共通の依存関係のキャッシングを可能にする。これは、ライブラリの変更でバンドル全体の再取得を要求しないことを保証します。
同時に、コード分割時に粒度が多すぎると悪い影響があります。なぜなら、多くの小さなチャンクは個々のチャンク圧縮率を低下させ、ブラウザパフォーマンスに影響するためです。
リソース最適化には、デッドコードまたは未使用コードの削除も必要です。不要または廃止された JS がモダンブラウザに配信されることが多く、これはパフォーマンスに悪影響を与えます。ES5 にトランスパイルされて polyfill とバンドルされた JS はモダンブラウザでは不要です。ライブラリと npm パッケージは多くの場合 ES モジュール形式で公開されていません。これにより、バンドラーが tree shake および最適化することを難しくしています。
お気付きの通り、これらの問題は特定のリソースセットまたはプラットフォームに限定されません。これらの問題を回避するには、テックスタック全体とさまざまなリソースを結合してメトリクスを最適化する方法の理解が必要です。
リソースに関するさらに詳しい情報 - 関係、制約、優先度
前のセクションでは、FCP や LCP などの特定のイベントが発火するために必要とされるリソースの例をいくつか提供しました。そのようなすべての依存関係を理解することから始めましょう。理想的なシーケンスを定義する前に、これらの関係、制約、注意点を理解する必要があります。以下はリソースごとの推奨、制約、注意事項のリストです。
重要な CSS
Critical CSS は FCP に必要な最小 CSS を指します。そのような CSS を別の CSS ファイルからインポートするのではなく、HTML 内にインライン化する方が優れています。任意の時点でそのルートに必要な CSS のみをダウンロードし、すべての重要な CSS をそれに応じて分割する必要があります。
インライン化が不可能な場合、重要な CSS は preload されて、ドキュメントと同じオリジンから提供される必要があります。複数のドメインから重要な CSS を提供したり、Google Fonts のような 3P 重要 CSS を直接使用したりすることを避けてください。独自のサーバーは 3P 重要 CSS のプロキシとして機能することができます。
CSS のフェッチの遅延またはフェッチの順序が間違っている場合、FCP と LCP に影響を与える可能性があります。これを回避するには、インラインされていない CSS を優先して、ネットワーク上で 1P JS と ATF 画像よりも上に配置する必要があります。
多すぎるインラインされた CSS は HTML の肥大化と、メインスレッド上のスタイル解析時間の長期化を引き起こします。これは FCP に悪影響を与える可能性があります。そのため、何が重要かを特定することとコード分割は重要です。
インラインされた CSS はキャッシュできません。この対処法の1つは、キャッシュ可能な CSS の重複リクエストを持つことです。ただし、これは複数の完全なページレイアウトを引き起こす可能性があり、FID に影響を与える可能性があることに注意してください。
フォント
重要な CSS と同様に、重要なフォント用の CSS もインライン化されるべきです。インライン化が不可能な場合は、スクリプトを preconnect 付きでロードする必要があります。フォントのフェッチ遅延(例: Google フォント、または異なるドメインのフォント)は FCP に影響を与える可能性があります。preconnect はブラウザにこれらのリソースへの接続をより早く確立するように指示します。
フォントをインライン化すると HTML が大幅に肥大化し、他の重要なリソースのフェッチを開始することが遅延する可能性があります。フォント フォールバックを使用して、FCP をブロック解除し、テキストを利用可能にすることができます。しかし、フォント フォールバックを使用すると、フォントが跳ね回るため、CLS に影響を与える可能性があります。また、実際のフォントが到着したときに、メインスレッド上で大きなスタイルとレイアウトタスクが発生する可能性があるため、FID に影響を与える可能性があります。
折り返し上 (ATF) 画像
これはページロード時にビューポート内にあるため、ユーザーに対して最初に表示される画像を指します。ATF 画像の特殊なケースはページのヒーロー画像です。すべての ATF 画像はサイズ設定されるべきです。サイズ設定されていない画像は、完全にレンダリングされたときに発生するレイアウトシフトのため、CLS メトリクスを低下させます。ATF 画像のプレースホルダーはサーバーによってレンダリングされるべきです。
遅延ヒーロー画像または空のプレースホルダーは、LCP の遅延をもたらします。さらに、プレースホルダーのサイズが実際のヒーロー画像の内在サイズと一致せず、画像が置換でオーバーレイされていない場合、LCP が再トリガーされます。理想的には、ATF 画像による FCP への影響はないはずですが、実際には画像が FCP をトリガーできます。
折り返し下 (BTF) 画像
これらはページロード時にユーザーに対して即座に表示されない画像です。そのため、これらは遅延ロードの理想的な候補です。これにより、1P JS またはページ上の重要な 3P と競合しないようになります。BTF 画像が 1P JS または重要な 3P リソースよりも前にロードされた場合、FID は遅延されます。
1P JavaScript
1P JS はアプリケーションのインタラクション準備状態に影響します。ネットワーク上の画像と 3P JS の背後で、そしてメインスレッド上の 3P JS の背後で遅延する可能性があります。したがって、ネットワーク上で ATF 画像より前にロード開始し、メインスレッド上で 3P JS より前に実行されるべきです。1P JS は、サーバーサイドでレンダリングされたページでは FCP と LCP をブロックしません。
3P JavaScript
HTML ヘッド内の 3P 同期スクリプトは CSS とフォント解析をブロックでき、したがって FCP をブロックする可能性があります。ヘッド内の同期スクリプトは、HTML ボディ解析もブロックします。メインスレッド上の 3P スクリプト実行は 1P スクリプト実行を遅延させ、ハイドレーションと FID を遅延させる可能性があります。したがって、3P スクリプトのローディングをより良く制御する必要があります。
これらの推奨と制約は、一般的にテックスタックとブラウザに関係なく適用されます。何かが推奨事項になれば、制約にもなる可能性があることに注意してください。例えば、フォントと CSS をインライン化することは良いことですが、多すぎると肥大化の原因となります。トリックは「遅すぎて少なすぎる」と「早すぎて多すぎる」のバランスを見つけることです。
以下は Chrome のリソース優先度テーブルからの主要な要点です:
- CSS とフォントは最優先度でロードされます。これは重要な CSS とフォントの優先順位付けを支援するはずです。
- スクリプトは、ドキュメント内の位置と async、defer、またはブロッキングであるかどうかに基づいて、異なる優先度を取得します。最初の画像(またはドキュメント内の早い段階の画像)より前にリクエストされるブロッキングスクリプトは、最初の画像がフェッチされた後にリクエストされるブロッキングスクリプトより高い優先度が与えられます。ドキュメント内のどこにあるかに関係なく、async/defer/injected スクリプトは最優先度です。したがって、async と defer に適切な属性を使用することで、異なるスクリプトの優先度を付けることができます。
- ビューポート内で表示されている画像は、ビューポート内にない画像 (Net: Lowest) よりも優先度が高い (Net: Medium) です。これにより、ATF 画像を BTF 画像よりも優先させることができます。
それでは、上記のすべての詳細がどのように結合されて、最適なローディングシーケンスを定義するかを見ていきましょう。
理想的なローディングシーケンスとは何か
この背景を踏まえて、1P と 3P の両方のリソースのローディングを最適化すべきローディングシーケンスを提案することができます。提案されたシーケンスは、最適化の参照として Next.js サーバーサイドレンダリング (SSR) を使用します。
現在の状態
弊社の経験に基づくと、以下は最適化前の典型的な Next.js SSR アプリケーションで観測されたローディングシーケンスです。
| リソース | 状態 |
|---|---|
| CSS | CSS は JS の前に preload されますが、インライン化されません |
| JavaScript | 1P JS は preload されます。3P JS は管理されておらず、ドキュメント内のどこにでも render-blocking である可能性があります。 |
| フォント | フォントはインライン化されておらず、preconnect も使用していません。フォントは外部スタイルシートを介してロードされ、ローディングが遅延します。フォントはディスプレイブロッキング、あるいはそうでない場合があります。 |
| 画像 | ヒーロー画像は優先順位付けされません。ATF と BTF 画像の両方は最適化されていません。 |
3P なしで提案されたシーケンス
以下は、前述のすべての制約を考慮したローディングシーケンスです。まず、3P なしのシーケンスに取り組みましょう。その後、このシーケンスに 3P リソースをどのようにインターリーブできるかを説明します。ここでは、Google Fonts を 1P と見なしていることに注意してください。
| # (メインスレッド) | イベント | # (ネットワーク) | リクエスト |
|---|---|---|---|
| 1 | HTML をパース | 1 | 小さなインライン 1P スクリプト |
| 2 | 小さなインライン 1P スクリプトを実行 | 2 | インライン化された重要 CSS (外部の場合は Preload) |
| 3 | インライン化された重要フォント (外部の場合は Preconnect) | ||
| 3 | FCP リソース (重要 CSS、フォント) をパース | 4 | LCP 画像 (外部の場合は Preconnect) |
| FCP | 5 | フォント (インラインフォント CSS からトリガー、Preconnect) | |
| 4 | LCP リソース (ヒーロー画像、テキスト) をレンダリング | 6 | 非重要 (async) CSS |
| 7 | インタラクティビティ用の 1P JS | ||
| 8 | 折り返し上の画像 (preconnect) | ||
| LCP | 9 | 折り返し下の画像 | |
| 5 | 重要な ATF 画像をレンダリング | ||
| Visually Complete | |||
| 6 | 非重要 (async) CSS をパース | ||
| 7 | 1P JS を実行してハイドレーション | 10 | 遅延ロード JS チャンク |
| FID |
このシーケンスの一部は直感的なものもありますが、以下の点はそれをさらに正当化するのに役立ちます。
- preload の使用をできるだけ避けることをお勧めします。なぜなら、preload は先行する各リソースで手動 preload を強制し、また順序付けの手動キュレーションを原因にするためです。preload は、重要なフォントを検出するのが難しいため、特にフォントで避けるべきです。
- フォント CSS は理想的にはインライン化されるべきです。別のオリジンからのフォントは preconnect を使用してフェッチされるべきです。
- preconnect は別のオリジンからのすべてのリソースについてお勧めされます。これにより、これらのリソースをダウンロードするために接続が事前に確立されることが保証されます。
- 非重要 CSS は、ユーザーインタラクション (FID) が始まる前にフェッチされるべきです。これにより、その後の CSS レンダリングによるスタイリング問題を回避できます。
- ネットワーク上で ATF 画像よりも前に 1P JS のフェッチを開始します。JS をダウンロード、パースするのに時間がかかります。
- メインスレッド上の HTML パースと ATF 画像のダウンロードは、1P JS がパースされている間に並行して続行できます。
3P を含む提案されたシーケンス
最後に、モダンなウェブアプリケーションで一般的にロードされるすべての主要なリソースのシーケンスを提案することができます。ブラウザメインスレッドのイベントとネットワークフェッチリクエストのシーケンスで 3P リソースが考慮された場合は以下のようになります。
| # | メインスレッドイベント | ネットワークリクエスト |
|---|---|---|
| 1 | HTML をパース | FCP ブロッキング 3P リソース |
| 2 | ||
| 3 | 小さなインライン 1P スクリプト | |
| 4 | 小さなインライン 1P スクリプトを実行 | インライン化された重要 CSS (外部の場合は Preload) |
| 5 | FCP ブロッキング 3P リソースをパース | インライン化された重要フォント (外部の場合は Preconnect) |
| 6 | FCP リソース (重要 CSS、フォント) をパース | LCP 用の 3P パーソナライズド ATF 画像 |
| 7 | FCP | LCP 画像 (外部の場合は Preconnect) |
| 8 | LCP 用の 3P パーソナライズド ATF 画像をレンダリング | フォント (インラインフォント CSS からトリガー、Preconnect) |
| 9 | 非重要 (async) CSS | |
| 10 | LCP リソース (ヒーロー画像、テキスト) をレンダリング | 最初のユーザーインタラクション前に実行する必要がある 3P |
| 11 | インタラクティビティ用の 1P JS | |
| 12 | LCP | |
| 13 | 重要な ATF 画像をレンダリング | デフォルト 3P JS |
| 14 | 非重要 (async) CSS をパース | |
| 15 | 最初のユーザーインタラクション前に実行する必要がある 3P を実行 | 折り返し下の画像 |
| 16 | 1P JS を実行してハイドレーション | 遅延ロード JS チャンク |
| FID | より重要度の低い 3P JS |
ここでの主な関心は、3P スクリプトが最適に、そして必要なシーケンスでダウンロードされることを保証する方法です。
スクリプトリクエストは別のドメインに行くため、以下の 3P リクエストに対して preconnect をお勧めします:
- #1 - FCP ブロッキング 3P リソース
- #5 - LCP 用の 3P パーソナライズド ATF 画像
- #9 - 最初のユーザーインタラクション前に実行する必要がある 3P
- #12 - デフォルト 3P JS
望むシーケンスを実現するために、Next 用の ScriptLoader コンポーネントの使用をお勧めします。このコンポーネントは「重要なレンダリングパスを最適化し、外部スクリプトが最適なページロードのボトルネックにならないようにする」ために設計されています。弊社の議論に最も関連する機能は、ローディング優先度です。これにより、異なるユースケースをサポートするために、異なるマイルストーンでスクリプトをスケジュール化できます。以下はご利用いただける優先度値です:
After-Interactive: 次のハイドレーション後に特定の 3P スクリプトをロードします。これを使用して、タグマネージャー、広告、または分析スクリプトをロードでき、1P スクリプトの後になるだけで、可能な限り早期に実行したい場合があります。
Before-Interactive: ハイドレーション前に特定の 3P スクリプトをロードします。3P スクリプトを 1P スクリプト前に実行したい場合に使用できます。例: polyfill.io、ボット検出、セキュリティと認証、ユーザーの同意管理 (GDPR) など。
Lazy-Onload: 指定された 3P スクリプトよりも他のすべてのリソースを優先し、スクリプトを遅延ロードします。Google フィードバックなどの CRM コンポーネントや、シェアボタン、コメントなどに使用されるソーシャルネットワーク固有のスクリプトに使用できます。
したがって、preconnect、スクリプト属性、および Next.js 用の ScriptLoader を組み合わせることで、すべてのスクリプトの望むシーケンスを実現するのに役立ちます。
結論
アプリ最適化の責任は、使用されるプラットフォームの作成者と、それを使用する開発者の両肩に掛かっています。一般的な問題には対処する必要があります。我々は、内側から外側へシーケンス化をより簡単にすることを目指しています。異なるユースケースの検証され、試行済みの一連の推奨事項と Script Loader のようなイニシアティブは、React-Next.js スタックに対してこれを実現するのに役立ちます。次のステップは、新しいアプリが上記の推奨事項に準拠することを保証することです。
出典
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- patternsdev
- リポジトリ
- patternsdev/skills
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/patternsdev/skills / ライセンス: MIT
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。