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

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 がウェブサイトのユーザーにどのように影響するかを観察する必要があります。TTFB はリダイレクトの影響を受けるため、TTFB を測定する主なソースとしてフィールドデータに依存する必要があります。一方、ラボベースのツールは最終的な URL を使用して測定されるため、この追加の遅延は測定されません。

PageSpeed Insights は、Chrome ユーザー エクスペリエンス レポートで利用可能な、一般公開されているウェブサイトのフィールド データとラボデータの両方を取得する方法の一つです。

実際のユーザーの 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 - $dbReadStartTime) / 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 プロトコルを使用して、HTTP/2 が依存する TCP に存在するヘッドオブライン ブロッキングの問題を解決します。
  • CDN は最新バージョンの TLS も提供しているため、TLS ネゴシエーション時間に関連するレイテンシを短縮できます。特に TLS 1.3 は、TLS ネゴシエーションをできるだけ短くするように設計されています。
  • 一部の CDN プロバイダは、「エッジ ワーカー」と呼ばれる機能を提供しています。これは、Service Worker API に似た API を使用して、リクエストをインターセプトしたり、エッジ キャッシュ内のレスポンスをプログラムで管理したり、レスポンスを完全に書き換えたりします。
  • CDN プロバイダは、圧縮の最適化に非常に優れています。圧縮は自分で正しく行うのが難しいため、動的に生成されたマークアップをその場で圧縮する必要がある場合、レスポンスが遅くなることがあります。
  • また、CDN プロバイダは、静的リソースの圧縮されたレスポンスを自動的にキャッシュに保存し、圧縮率とレスポンス時間の最適な組み合わせを実現します。

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

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

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

コンテンツを頻繁に更新するサイトでは、キャッシュに保存する時間が短くても、トラフィックの多いサイトではパフォーマンスが大幅に向上する可能性があります。その期間にアクセスした最初のユーザーのみが送信元サーバーにアクセスする際にレイテンシが発生しますが、他のすべてのユーザーはエッジサーバーからキャッシュに保存されたリソースを再利用できるからです。一部の CDN では、サイトのリリース時にキャッシュの無効化を許可しているため、キャッシュの保持期間を長くしながら、必要に応じて即時更新できるというメリットがあります。

キャッシュが正しく設定されている場合でも、アナリティクスの測定に固有のクエリ文字列パラメータを使用すると、この問題を無視できます。同じコンテンツであっても、CDN から見ると異なるコンテンツのように見えるため、キャッシュに保存されたバージョンは使用されません。

古いコンテンツやアクセス頻度の低いコンテンツはキャッシュに保存されていない場合があり、その結果、一部のページの TTFB 値が他のページよりも高くなることがあります。キャッシュ時間の増加により、この影響を軽減できますが、キャッシュ時間の増加に伴い、古いコンテンツが配信される可能性も高くなります。

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

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

TTFB の増加につながる一般的な要因の 1 つはリダイレクトです。リダイレクトは、ドキュメントのナビゲーション リクエストで、リソースが別の場所にあることをブラウザに通知するレスポンスが受信された場合に発生します。1 つのリダイレクトによって、ナビゲーション リクエストに望ましくないレイテンシが追加される可能性がありますが、そのリダイレクトが別のリソースを参照し、別のリダイレクトが発生すると、さらに悪化する可能性があります。特に、広告やニュースレターから大量のユーザーが訪れるサイトでは、測定目的で分析サービス経由でリダイレクトされることが多いため、影響が大きく出る可能性があります。直接管理しているリダイレクトを削除すると、TTFB を改善できます。

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

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

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

クロスオリジン リダイレクトは、多くの場合管理できないため、より複雑になりますが、可能であれば複数のリダイレクトを避けてください。たとえば、リンクを共有する際に複数のリンク短縮ツールを使用するなどです。広告主またはニュースレターに指定した URL が正しい最終ページ URL であることを確認してください。そうすることで、これらのサービスで使用されているリダイレクトに別のリダイレクトを追加する必要がなくなります。

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

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

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

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

ブラウザはストリーミング マークアップを処理するのに優れていますが、最初のマークアップ ビットができるだけ早く送信されるように、ストリーミングを維持するためにできる限りのことをすることが重要です。バックエンドが処理を遅らせている場合は、問題です。バックエンド スタックは多数あるため、すべてのスタックと、各スタックで発生する可能性のある問題を網羅することは、このガイドの範囲を超えています。

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

マークアップをブラウザに迅速にストリーミングするもう 1 つの方法は、ビルド時に HTML ファイルを生成する静的レンダリングを使用することです。ファイル全体をすぐに利用できる状態にしておけば、ウェブサーバーはファイルをすぐに送信できます。HTTP の性質上、マークアップはストリーミングされます。このアプローチは、ユーザー エクスペリエンスの一部として動的レスポンスを必要とするページなど、すべてのウェブサイトのすべてのページに適しているわけではありませんが、特定のユーザーに合わせてマークアップをパーソナライズする必要がないページには有効です。

サービス ワーカーを使用する

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

  • アセットにStale-while-revalidate 戦略を使用する。アセットが Service Worker キャッシュ内にある場合(ドキュメントまたはドキュメントに必要なリソース)、Stale-while-revalidate 戦略では、そのリソースを最初にキャッシュから提供し、次にそのアセットをバックグラウンドでダウンロードして、今後の操作のためにキャッシュから提供します。
    • 変更頻度の低いドキュメント リソースがある場合は、Stale-while-revalidate 戦略を使用すると、ページの TTFB をほぼ瞬時にすることができます。ただし、ウェブサイトが動的に生成されたマークアップ(ユーザーの認証状況に応じて変化するマークアップなど)を送信する場合は、この方法は適していません。このような場合は、ドキュメントをできるだけ最新の状態に保つため、常にネットワークを先に参照します。
    • ドキュメントで、頻繁に変更されるが、古いリソースを取得してもユーザー エクスペリエンスに大きな影響を与えないリソース(特定の画像やその他の重要でないリソースなど)を読み込む場合は、古いリソースを取得しながら再検証する戦略を使用して、これらのリソースの TTFB を大幅に短縮できます。
  • クライアント レンダリング アプリケーションにはアプリシェル モデルを使用します。このモデルは、ページの「シェル」をサービス ワーカー キャッシュから即座に配信でき、ページの動的コンテンツがページのライフサイクルの後半で入力されてレンダリングされる SPA に最適です。

レンダリングに重要なリソースには 103 Early Hints を使用する

アプリケーション バックエンドがどれほど最適化されていても、レスポンスの準備のためにサーバーが行う必要がある作業が大量に発生する可能性があります。これには、ナビゲーション レスポンスが可能な限り迅速に届かなくなる、費用のかかる(しかし必要な)データベース処理が含まれます。この場合、CSS や、場合によってはクライアントでマークアップをレンダリングする JavaScript など、レンダリングに不可欠な後続のリソースが遅延する可能性があります。

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

まとめ

バックエンド アプリケーション スタックの組み合わせは非常に多いため、ウェブサイトの TTFB を短縮するためにできることをすべて網羅した記事は存在しません。ただし、サーバーサイドで処理を少しでも速くするために、以下の方法を検討できます。

他の指標の最適化と同様に、アプローチはほぼ同じです。フィールドで TTFB を測定し、ラボツールを使用して原因をドリルダウンし、可能であれば最適化を適用します。ここに記載されているテクニックはすべて、お客様の状況に適しているわけではありませんが、一部は適している可能性があります。いつものように、フィールドデータを注意深く確認し、必要に応じて調整して、可能な限り高速なユーザー エクスペリエンスを実現する必要があります。

ヒーロー画像: Taylor Vick、Unsplash より