最初のバイトまでの時間を最適化する

Time to First Byte(最初のバイトまでの時間)指標を最適化する方法を学習します。

Time to First Byte(TTFB)は、First Contentful Paint(FCP)Largest Contentful Paint(LCP)など、他のすべての有意義なユーザー エクスペリエンス指標に先行する基本的なウェブ パフォーマンス指標です。つまり、TTFB 値が大きいと、それに続く指標の時間が長くなります。

ユーザーの 75 パーセンタイルで FCP が「良好」のしきい値内に収まるように、サーバーがナビゲーション リクエストに迅速に応答することをおすすめします。目安として、ほとんどのサイトでは TTFB を 0.8 秒以下にすることをおすすめします。

良好な TTFB 値は 0.8 秒以下で、低値は 1.8 秒を超えていて、その中間値は改善が必要

TTFB の測定方法

TTFB を最適化する前に、ウェブサイトのユーザーへの影響を確認する必要があります。TTFB はリダイレクトの影響を受けるため、主なソースとしてフィールド データを利用してください。一方、ラボベースのツールは最終ページ URL を使用して測定されることが多いため、この余分な遅延は発生しません。

PageSpeed Insights は、Chrome ユーザー エクスペリエンス レポートで参照できる公開ウェブサイトのフィールド情報とラボ情報の両方を取得する 1 つの方法です。

実際のユーザーの TTFB は、上部の [実際のユーザーの状況を確認する] セクションに表示されます。

PageSpeed Insights の実際のユーザーデータ(TTFB 指標のフィールド データなど)。

TTFB のサブセットは、サーバー レスポンス時間監査に表示されます。

サーバーの応答時間の監査

フィールドとラボの両方で TTFB を測定する方法について詳しくは、TTFB 指標のページをご覧ください。

Server-Timing を使用してフィールドの高い TTFB をデバッグする

高レイテンシの原因となる可能性のある個別のバックエンド プロセスを測定するために、アプリケーションのバックエンドで Server-Timing レスポンス ヘッダーを使用できます。ヘッダー値の構造は柔軟で、少なくとも自分で定義したハンドルを受け入れることができます。省略可能な値には、期間の値(dur を使用)と、人間が読める形式の説明(desc を使用)があります。

Serving-Timing を使用すると、多くのアプリケーション バックエンド プロセスを測定できますが、特に注意が必要なプロセスがいくつかあります。

  • データベース クエリ
  • サーバー側のレンダリング時間(該当する場合)
  • ディスクのシーク
  • エッジサーバーのキャッシュ ヒット/ミス(CDN を使用している場合)

Server-Timing エントリのすべての部分はコロンで区切られ、複数のエントリはカンマで区切ることができます。

// Two metrics with descriptions and values
Server-Timing: db;desc="Database";dur=121.3, ssr;desc="Server-side Rendering";dur=212.2

このヘッダーは、アプリケーション バックエンドの任意の言語を使用して設定できます。たとえば PHP では、次のようにヘッダーを設定できます。

<?php
// Get a high-resolution timestamp before
// the database query is performed:
$dbReadStartTime = hrtime(true);

// Perform a database query and get results...
// ...

// Get a high-resolution timestamp after
// the database query is performed:
$dbReadEndTime = hrtime(true);

// Get the total time, converting nanoseconds to
// milliseconds (or whatever granularity you need):
$dbReadTotalTime = ($dbReadEndTime - $dbReadStarTime) / 1e+6;

// Set the Server-Timing header:
header('Server-Timing: db;desc="Database";dur=' . $dbReadTotalTime);
?>

このヘッダーを設定すると、ラボフィールドの両方で使用できる情報が表示されます。

このフィールドに Server-Timing レスポンス ヘッダーが設定されているページは、Navigation Timing APIserverTiming プロパティに入力されます。

// Get the serverTiming entry for the first navigation request:
performance.getEntries('navigation')[0].serverTiming.forEach(entry => {
  // Log the server timing data:
  console.log(entry.name, entry.description, entry.duration);
});

ラボでは、Server-Timing レスポンス ヘッダーからのデータが Chrome DevTools の [Network] タブにあるタイミングパネルで可視化されます。

Chrome DevTools の [Network] タブに表示された Server-Timing ヘッダー値の図。この図の Server-Timing ヘッダー値は、CDN エッジサーバーでキャッシュ ヒットまたはキャッシュミスが発生したかどうかと、エッジと配信元サーバーからリソースを取得する時間を測定しています。

Chrome DevTools の [ネットワーク] タブに表示された Server-Timing レスポンス ヘッダー。ここでは、Server-Timing を使用して、リソースに対するリクエストが CDN キャッシュにヒットしたかどうかと、リクエストが CDN のエッジサーバーに到達してから送信元に到達するまでにかかる時間を測定します。

利用可能なデータを分析して TTFB に問題があると判断したら、問題の解決に進みます。

TTFB を最適化する方法

TTFB を最適化するうえで最も難しい点は、ウェブのフロントエンド スタックは常に HTML、CSS、JavaScript であるのに、バックエンド スタックが大きく異なる可能性があることです。バックエンド スタックやデータベース プロダクトは数多く存在し、それぞれに独自の最適化手法があります。そのため、このガイドでは、スタック固有のガイダンスだけに焦点を当てるのではなく、ほとんどのアーキテクチャに当てはまるものに焦点を当てます。

プラットフォーム固有のガイダンス

ウェブサイトで使用しているプラットフォームは、TTFB に大きな影響を与える可能性があります。たとえば、WordPress のパフォーマンスは、プラグインの数や品質、使用されているテーマに影響されます。プラットフォームがカスタマイズされている場合、他のプラットフォームにも同様の影響があります。この投稿で紹介する一般的なパフォーマンスに関するアドバイスを補完するために、ベンダー固有のアドバイスについては、ご使用のプラットフォームのドキュメントをご覧ください。サーバーの応答時間を短縮するための Lighthouse 監査には、スタック固有の限定的なガイダンスも含まれています。

ホスティング、ホスティング、ホスティング

他の最適化アプローチを検討する前に、まずホスティングについて検討する必要があります。ここで提供できる具体的なガイダンスはあまりありませんが、一般的な経験則として、ウェブサイトに送信されるトラフィックをウェブサイトのホストが処理できることを確認してください。

通常、共有ホスティングは遅くなります。主に静的ファイルを配信する小規模な個人ウェブサイトを運営している場合は、おそらくこれで十分です。また、以下の最適化手法を活用することで、TTFB を可能な限り減らすことができます。

しかし、パーソナライズ、データベース クエリ、その他の負荷の高いサーバーサイド オペレーションを伴う、多数のユーザーを抱える大規模なアプリケーションを実行している場合は、現場の TTFB を短縮するためにホスティングの選択が重要になります。

ホスティングプロバイダーを選ぶときは、次の点に注意しましょう。

  • アプリケーション インスタンスに割り当てられているメモリの量はどれくらいですか。アプリケーションのメモリが不足していると、スラッシングが発生し、ページをすぐに表示するのに苦労します。
  • ホスティング プロバイダはバックエンド スタックを最新の状態に保っていますか?アプリケーション バックエンド言語、HTTP 実装、データベース ソフトウェアの新しいバージョンがリリースされると、それらのソフトウェアのパフォーマンスは時間の経過とともに向上します。このような重要なメンテナンスを優先するホスティング プロバイダと提携することが重要です。
  • 非常に特殊なアプリケーション要件があり、サーバー構成ファイルへの最低レベルのアクセスが必要な場合は、独自のアプリケーション インスタンスのバックエンドをカスタマイズしてもよいかどうかを尋ねます。

こういったことを行うホスティング プロバイダは数多く存在しますが、専用のホスティング プロバイダであっても TTFB 値が長くなり始めた場合は、現在のホスティング プロバイダの機能を再評価して可能な限り最良のユーザー エクスペリエンスを提供できるようにする必要がある兆候かもしれません。

コンテンツ配信ネットワーク(CDN)を使用する

CDN の使用状況というトピックはよく使われていますが、十分に最適化されたアプリケーション バックエンドを使用できるとしても、配信元サーバーから離れた場所にいるユーザーの TTFB が依然として高いという理由でもあります。

CDN は、配信元サーバーからユーザーが近いという問題を解決するため、分散したサーバー ネットワークを使用して、ユーザーの物理的に近いサーバー上にリソースをキャッシュします。これらのサーバーはエッジサーバーと呼ばれます。

CDN プロバイダは、エッジサーバー以外にも次のようなメリットを提供する可能性があります。

  • CDN プロバイダは通常、非常に高速な DNS 解決時間を提供します。
  • CDN は、HTTP/2 や HTTP/3 などの最新のプロトコルを使用してエッジサーバーからコンテンツを配信する可能性があります。
  • 特に HTTP/3 は、UDP プロトコルを使用することで、TCP に存在するヘッドオブライン ブロッキング問題(HTTP/2 が依存しているもの)を解決します。
  • CDN では最新バージョンの TLS が提供されるため、TLS ネゴシエーション時のレイテンシが短縮されます。特に、TLS 1.3 は TLS ネゴシエーションを可能な限り短くするように設計されています。
  • 一部の CDN プロバイダは、「エッジワーカー」と呼ばれる機能を提供しています。エッジワーカーは、Service Worker API に似た API を使用して、リクエストのインターセプト、エッジ キャッシュ内のレスポンスのプログラマティック管理、レスポンス全体の書き換えを行います。
  • CDN プロバイダは圧縮の最適化に優れています。圧縮をご自身で行うのは難しく、動的に生成されるマークアップでは応答時間が遅くなる可能性があります。このようなマークアップはその場で圧縮する必要があります。
  • CDN プロバイダは、静的リソースの圧縮レスポンスを自動的にキャッシュに保存するため、圧縮率とレスポンス時間の組み合わせを最適化できます。

CDN を導入する労力は、些細なものから重大なものまでさまざまですが、ウェブサイトでまだ TTFB を使用していない場合は、TTFB を最適化するために優先的に取り組む必要があります。

可能であれば、キャッシュに保存されたコンテンツを使用する

CDN では、適切な Cache-Control HTTP ヘッダーでコンテンツが構成されていれば、物理的に訪問者に近いエッジサーバーでコンテンツをキャッシュに保存できます。これはパーソナライズされたコンテンツには適していませんが、送信元まで遡る必要があると、CDN の価値の多くが損なわれる可能性があります。

コンテンツを頻繁に更新するサイトの場合、キャッシュ時間が短い場合でも、ビジー状態のサイトのパフォーマンスが大幅に向上する可能性があります。これは、その間に最初の訪問者のみが配信元サーバーへの完全なレイテンシを経験し、他のすべての訪問者はエッジサーバーからキャッシュされたリソースを再利用できるためです。一部の CDN では、サイトのリリースでキャッシュを無効化できるため、両方の長所を活かすことができ、キャッシュ時間は長くなりますが、必要に応じて即座に更新されます。

キャッシュ保存が正しく構成されていても、分析測定に一意のクエリ文字列パラメータを使用することで、この状態を無視できます。これらは同じものであっても、CDN には異なるコンテンツとして見えることがあるため、キャッシュ バージョンは使用されません。

アクセスが古いコンテンツやアクセス頻度の低いコンテンツもキャッシュに保存されないため、ページによって TTFB 値が他のページより高くなる可能性があります。キャッシュ保存時間を長くすると影響を軽減できますが、キャッシュ時間が長くなるほど、古いコンテンツが配信される可能性が高くなるので注意してください。

キャッシュに保存されたコンテンツの影響は、CDN を使用しているコンテンツだけでなく、キャッシュされたコンテンツを再利用できない場合、サーバー インフラストラクチャはコストのかかるデータベース ルックアップからコンテンツを生成しなければならない場合があります。多くの場合、アクセス頻度が高いデータや事前キャッシュ ページを使用すると、パフォーマンスが向上します。

複数のページ リダイレクトを避ける

TTFB が高くなる一般的な原因の一つは、リダイレクトです。リダイレクトは、ドキュメントのナビゲーション リクエストが、リソースが別の場所に存在することをブラウザに通知するレスポンスを受け取った場合に発生します。あるリダイレクトによって、ナビゲーション リクエストに不要なレイテンシが加わる可能性がありますが、そのリダイレクトが別のリソースをポイントし、その結果、別のリダイレクトなどが発生すると、確実に悪化する可能性があります。広告やニュースレターは測定目的でアナリティクス サービスにリダイレクトされることが多いため、そうしたサイトからアクセス数の多いサイトは、特に大きな影響を及ぼします。直接制御下でリダイレクトをなくすと、優れた TTFB を達成できます。

リダイレクトには次の 2 種類があります。

  • 同一オリジン リダイレクト: ウェブサイト上でリダイレクトをすべて行います。
  • クロスオリジン リダイレクト。リダイレクトは、最初に別のオリジン(ソーシャル メディアの URL 短縮サービスなど)からウェブサイトに到達する前に行われます。

同一オリジン リダイレクトはお客様が直接管理できるため、排除することに重点を置いてください。これには、ウェブサイト上のリンクをチェックして、いずれかのリンクが 302 または 301 レスポンス コードを返すかどうかを確認する必要があります。多くの場合、これは https:// スキームが含まれていないか(ブラウザはデフォルトで http:// に設定され、その後リダイレクトされる)、または末尾のスラッシュが URL に適切に含まれていない、または除外されていないことが原因です。

クロスオリジン リダイレクトは自分で管理できないことが多いため、注意が必要ですが、可能な限り複数のリダイレクトは避ける(リンクを共有するときに複数の短縮リンクを使用するなど)。広告主様やニュースレターに提供する URL が正しいことをご確認ください。最終ページ URL が正しいことをご確認ください。そうすることで、そうしたサービスで使用するものにリダイレクトされるのを防ぐことができます。

リダイレクト時間のもう一つの重要な原因は、HTTP から HTTPS へのリダイレクトです。これを回避する 1 つの方法は、Strict-Transport-Security ヘッダー(HSTS)を使用して、オリジンへの初回アクセス時に HTTPS を適用し、今後のアクセスでは HTTPS スキームを介してオリジンにすぐにアクセスできるようにブラウザに伝えることです。

適切な HSTS ポリシーを策定したら、サイトを HSTS プリロード リストに追加することで、オリジンへの初回アクセスを高速化できます。

マークアップをブラウザにストリーミングする

ブラウザは、ストリーミングされるときにマークアップを効率的に処理するように最適化されています。つまり、マークアップはサーバーから送信される際にチャンクで処理されます。これは、大きなマークアップ ペイロードが関係している場合に非常に重要です。ブラウザは、レスポンス全体が到着して解析が始まるのを待つのではなく、マークアップのチャンクを段階的に解析できるからです。

ブラウザはストリーミング マークアップの処理に優れていますが、マークアップの最初の部分ができるだけ早く実装されるように、ストリームの流れを維持するために可能な限り行うことが重要です。バックエンドで処理が停止している場合でも、それは問題です。バックエンド スタックは膨大なため、すべてのスタックと、特定のバックエンド スタックで発生する可能性がある問題については、このガイドでは説明しません。

たとえば React や、サーバー上でオンデマンドでマークアップをレンダリングできる他のフレームワークでは、サーバーサイド レンダリングに同期的なアプローチを採用してきました。ただし、新しいバージョンの React では、レンダリング時にマークアップをストリーミングするためのサーバー メソッドが実装されています。つまり、React サーバーの API メソッドがレスポンス全体をレンダリングするのを待たずに送信できるということです。

マークアップがブラウザにすばやくストリーミングされるようにするもう 1 つの方法は、ビルド時に HTML ファイルを生成する静的レンダリングを使用することです。ファイル全体が即座に取得されるため、ウェブサーバーはすぐにファイルの送信を開始できます。HTTP の本質的な性質により、ストリーミング マークアップが発生します。この方法は、ユーザー エクスペリエンスの一部として動的レスポンスを必要とするページなど、すべてのウェブサイトのすべてのページに適しているわけではありませんが、マークアップを特定のユーザー用にパーソナライズする必要がないページに対しては有益です。

Service Worker を使用する

Service Worker API は、ドキュメントとそれらが読み込むリソースの両方の TTFB に大きな影響を与える可能性があります。その理由は、Service Worker がブラウザとサーバー間のプロキシとして機能するためです。ただし、ウェブサイトの TTFB に影響するかどうかは、Service Worker の設定方法と、その設定がアプリケーションの要件と一致するかどうかによって異なります。

  • アセットに対して古い再検証戦略を使用する。アセットが Service Worker のキャッシュにある場合(ドキュメントであれ、ドキュメントに必要なリソースであれ)、stale-while-revalidate 戦略はそのリソースを最初にキャッシュから処理してから、そのアセットをバックグラウンドでダウンロードし、今後の操作のためにキャッシュから提供します。
    • あまり変更されないドキュメント リソースがある場合、古い再検証戦略を使用すると、ページの TTFB をほぼ瞬時に行うことができます。ただし、ユーザーの認証に応じて変化するマークアップなど、動的に生成されたマークアップがウェブサイトから送信される場合は、うまく機能しません。そのような場合は、常に最初にネットワークに接続して、ドキュメントができるだけ新しい状態になるようにします。
    • ドキュメントが一定の頻度で変化する重要性の低いリソースを読み込んでも、古いリソースを取得してもユーザー エクスペリエンスに大きな影響を及ぼさない場合(重要度の低い画像やその他のリソースを選択するなど)、そのようなリソースの TTFB は、古い再検証戦略を使用して大幅に削減できます。
  • クライアントでレンダリングされるアプリケーションには App Shell モデルを使用します。このモデルは、ページの「シェル」が Service Worker のキャッシュから即座に配信され、ページの動的コンテンツがページ ライフサイクルの後半で入力およびレンダリングされる SPA に最適です。

レンダリング クリティカルなリソースに 103 Early Hints を使用する

アプリケーションのバックエンドがどれだけ最適化されていても、サーバーがレスポンスを準備するために、負荷の高い(ただし必要な)データベース処理など、ナビゲーション レスポンスができるだけ早く届くのを遅らせるデータベース処理の大量処理が必要になることがあります。これにより、クライアントでマークアップをレンダリングする CSS や、場合によっては JavaScript など、後続のレンダリング クリティカルなリソースの遅延が発生する可能性があります。

103 Early Hints ヘッダーは、バックエンドがマークアップの準備中にサーバーがブラウザに送信できる早期レスポンス コードです。このヘッダーを使用すると、マークアップの準備中にページでダウンロードを開始する必要がある、レンダリングに不可欠なリソースがあることをブラウザに示すことができます。対応ブラウザの場合は、ドキュメントのレンダリング(CSS)が速くなり、ページのコア機能(JavaScript)をより早く利用できるようになります。

おわりに

バックエンド アプリケーション スタックの組み合わせは多種多様であるため、ウェブサイトの TTFB を短縮するためにできることすべてを網羅した 1 つの記事はありません。ただし、サーバー側での処理をもう少し速く実行できるオプションがいくつかあります。

すべての指標を最適化する場合と同様に、手法はほぼ同じです。現場で TTFB を測定し、ラボツールを使用して原因をドリルダウンし、可能であれば最適化を適用します。ここで紹介したすべての手法が状況に対して有効というわけではありませんが、中には有効なものもあるでしょう。これまでと同様に、フィールド データを常に注視し、可能な限り高速なユーザー エクスペリエンスを実現するため、必要に応じて調整する必要があります。

ヒーロー画像提供: Taylor Vick(出典: Unsplash)