Cloud CDN は、App Hosting がウェブアプリをサポートするうえで重要な役割を果たします。バックエンドへのリクエストはすべて、まず Cloud CDN を経由します。CDN にすでにキャッシュされているコンテンツは、ウェブアプリのサーバーコードを実行している Cloud Run サービスへのアクセスをスキップして、すぐにユーザーに返されます。CDN の一般的なメリットについては、web.dev をご覧ください。
基本的な Cloud CDN 構成は App Hosting によって設定され、変更できませんが、キャッシュを最適化してページ読み込み速度を向上させ、課金対象のキャッシュに保存されていないコンテンツを減らし、Cloud Run へのトラフィックを最小限に抑えることができます。
キャッシュに保存可能なコンテンツ
Cloud CDN は、次の条件がすべて満たされている場合にレスポンスをキャッシュに保存します。
リクエストが GET である
レスポンスのステータス コードが
200、203、204、206、300、301、302、307、308、404、405、410、421、451、501のいずれかである。レスポンスには、
max-ageまたはs-maxageディレクティブを含むCache-Controlヘッダー、あるいは将来のタイムスタンプを含むExpiresヘッダーがあります。レスポンスに
AgeヘッダーまたはCache-Controlヘッダーがあり、明示的なpublicディレクティブが含まれている。レスポンスのサイズが 10 MiB 以下である。
かつ、次のいずれにも該当しない場合:
レスポンスに
Set-Cookieヘッダーがあるレスポンスに、
Accept、Accept-Encoding、Access-Control-Request-Headers、Access-Control-Request-Method、Origin、Sec-Fetch-Dest、Sec-Fetch-Mode、Sec-Fetch-Site、X-Goog-Allowed-Resources、X-Origin、RSC、Next-Router-State-Tree、Next-Router-Prefetch、Next-Router-Segment-Prefetch、Next-Url以外の値を持つVaryヘッダーがある。レスポンスには、
no-storeまたはprivateディレクティブを含むCache-Controlヘッダーがあります。リクエストには、
no-storeディレクティブを含むCache-Controlヘッダーがあります。レスポンスに明示的なキャッシュ制御ディレクティブがない限り、リクエストには
Authorizationヘッダーがあります。
キャッシュ制御ディレクティブを使用して動作をカスタマイズする
Next.js
Next.js は、さまざまな要因に基づいて、cache-control ディレクティブを暗黙的に設定します。ただし、next.config.js ファイルでヘッダーを設定することで、これらをオーバーライドできます。たとえば、ページが Cloud CDN にキャッシュされないようにするには、次のようにします。
/** @type {import('next').NextConfig} */
const nextConfig = {
headers: async () => [{
source: "/YOUR_PRIVATE_PAGE",
headers: [{
key: "Cache-Control",
value: "private"
}],
}],
};
Angular
Angular SSR は、明示的な cache-control ディレクティブをデフォルトで設定しません。サーバー ルートで cache-control ヘッダーを指定することで、独自のヘッダーを追加できます。たとえば、Cloud CDN がすべてのページを 1 時間キャッシュできるようにするには、次のようにします。
import { RenderMode, ServerRoute } from '@angular/ssr';
export const serverRoutes: ServerRoute[] = [
{
path: '**',
renderMode: RenderMode.Prerender,
headers: {
'Cache-Control': 'public, max-age=3600',
}
}
];
特定のページがキャッシュされないようにするには、次のようにします。
import { RenderMode, ServerRoute } from '@angular/ssr';
export const serverRoutes: ServerRoute[] = [
// ... other routes
{
path: 'YOUR_PRIVATE_PAGE',
renderMode: RenderMode.Server,
headers: {
'Cache-Control': 'private',
}
}
];
重視されるディレクティブ
Firebase App Hosting の Cloud CDN インスタンスは、次のキャッシュ制御ディレクティブを遵守します。
| ディレクティブ | リクエスト | レスポンス |
|---|---|---|
no-store |
リクエストに存在する場合、レスポンスはキャッシュに保存されません。 | no-store を含むレスポンスはキャッシュに保存されません。 |
no-cache |
no-cache リクエスト ディレクティブは無視され、クライアントが送信元に対する再検証を開始または強制する可能性が回避されます。 |
no-cache を含むレスポンスはキャッシュに保存されますが、提供される前に送信元との再検証が必要です。 |
public |
なし | このディレクティブはキャッシュ可能性に必須ではありませんが、プロキシによってキャッシュされるべきコンテンツに含めることがベスト プラクティスです。 |
private |
なし | private ディレクティブを含むレスポンスは、レスポンスがその他の理由でキャッシュ保存可能であるとみなされる場合でも、Cloud CDN によってキャッシュに保存されません。クライアント(ブラウザなど)は、引き続き結果をキャッシュに保存する可能性があります。レスポンスのキャッシュへの保存をすべて回避するには、no-store を使用します。 |
max-age=SECONDS |
max-age リクエスト ディレクティブは無視されます。キャッシュに保存されたレスポンスは、このヘッダーがリクエストに含まれていない場合と同様に返されます。 |
max-age ディレクティブを含むレスポンスは、最大で SECONDS までキャッシュに保存されます。 |
s-maxage=SECONDS |
なし | s-maxage ディレクティブを含むレスポンスは、最大で SECONDS までキャッシュに保存されます。max-age と s-maxage の両方が存在する場合、s‑maxage が Cloud CDN で使用されます。このディレクティブを含むレスポンスは、古い状態で提供されません。s-max-age(2 つのハイフン)は、キャッシュを保存する目的に対しては無効です。 |
max-stale=SECONDS |
max-stale リクエスト ディレクティブは、クライアントが許容する最大鮮度(秒単位)を指定します。Cloud CDN はこれを遵守し、レスポンスのステイルネスが max-stale ディレクティブより小さい場合にのみ、古いキャッシュ レスポンスを返します。それ以外の場合は、リクエストを処理する前に再検証します。 |
なし |
stale-while-revalidate=SECONDS |
なし | 再検証が非同期で行われている間、stale-while-revalidate を含むレスポンスが最大 SECONDS 秒間クライアントに提供されます。 |
must-revalidate |
なし | must-revalidate を含むレスポンスは、有効期限が切れると配信元サーバーで再検証されます。このディレクティブを含むレスポンスは、古い状態で提供されません。 |
proxy-revalidate |
proxy-revalidate を含むレスポンスは、有効期限が切れると配信元サーバーで再検証されます。このディレクティブを含むレスポンスは、古い状態で提供されません。 |
|
no-transform |
なし | Cloud CDN で変換は適用されません。 |
キャッシュに保存されたトラフィックとキャッシュに保存されていないトラフィックを測定する
Firebase コンソールの [App Hosting] > [使用状況] タブの [Cloud CDN - 送信帯域幅] グラフには、キャッシュされたバイト数とキャッシュされていないバイト数が表示され、ロールアウトごとにマークが付けられます。このグラフを使用して、キャッシュ最適化の取り組みの効果を測定できます。
ルートベースのモニタリングを使用して、ウェブアプリの特定のルートのキャッシュ ヒット率を表示することもできます。