Cloud CDN は、ウェブアプリの App Hosting のサポートの重要な部分です。バックエンドへのリクエストはすべて、最初に Cloud CDN を通過します。CDN にすでにキャッシュ保存されているコンテンツは、ウェブアプリのサーバーコードを実行している Cloud Run サービスへのアクセスをスキップして、ユーザーにすぐに返されます。CDN の一般的なメリットについては、web.dev をご覧ください。
基本的な Cloud CDN 構成は App Hosting によって設定され、変更できませんが、キャッシュを最適化してページ読み込み速度を向上させ、課金対象のキャッシュ未保存コンテンツを減らし、Cloud Run へのトラフィックを最小限に抑えるために、さまざまな方法があります。
キャッシュに保存可能なコンテンツ
次の条件がすべて true の場合、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ヘッダーまたは明示的なpublicディレクティブを含むCache-Controlヘッダーがあります。レスポンスのサイズが 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以外の値が設定された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 ディレクティブはデフォルトで設定されません。サーバー ルートでキャッシュ制御ヘッダーを指定することで、独自のものを追加できます。たとえば、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 で変換は適用されません。 |
キャッシュに保存されたトラフィックとキャッシュに保存されていないトラフィックを測定する
App Hosting コンソールの [使用量] タブの [Cloud CDN - 送信帯域幅] グラフには、キャッシュに保存されたバイト数とキャッシュに保存されていないバイト数が表示され、各ロールアウトのマークが表示されます。このグラフを使用して、キャッシュの最適化の取り組みの効果を測定できます。
ルートベースのモニタリングを使用して、ウェブアプリ内の特定のルートのキャッシュ ヒット率を表示することもできます。