Firebaseで動的に情報を出力する場合にCloudFunctionsを利用するわけですが、頻繁に情報が変化しない場合など実行結果を一定時間キャッシュしたくなりますよね。Firebaseでは非常に手軽に実装できます。
結論から言うと以下のようにCache-Control
ヘッダを出力するだけ。以下で30秒間Firebaseが用意するCDNに実行結果がキャッシュされます。public
のつけ忘れにご注意を。
res .set("Cache-Control", "public, max-age=30") .send("キャッシュされるよ");
最初これを知らずにCDNを別途用意して、Firebase側をオリジンに設定しようとしていましたw 危ない危ないw
サンプル
実行例
以下から実際に動作を確認できます。 https://miku3.net/cdnCacheTestmiku3.net
現在時間を出力するプログラムですが、CDNに30秒間キャッシュされるため再読み込みしてもその間は表示が変化しません。
コード
実行例のコードです。
exports.CDNCacheTest = functions.https.onRequest( (req, res) => { const now = new Date(); const mm = ("00" + now.getMinutes()).slice(-2); const ss = ("00" + now.getSeconds()).slice(-2); res .set("Cache-Control", "public, max-age=30") .send( `<h1>${mm}:${ss}</h1>` + "<p><small>30秒間CDNにキャッシュします</small></p>" ); });
Cache-Controlヘッダ
これはFirebaseというよりHTTPの仕様ですが、今回のブログの内容に置き換えてメモしておきます。例えば「CDN」とある箇所は本来はプロキシなどその他の中間サーバも指します。
public
デフォルトでprivate
が指定されているのですがprivate
のままだとCDNにキャッシュされません。そのため必ずpublic
を指定する必要があります。
max-ageとs-maxage
Cache-Controlヘッダでは以下のようにmax-ageとs-maxageの2つの値を指定できます。
res.set("Cache-Control", "public, max-age=300, s-maxage=600")
それぞれ以下のような意味を持ちます。
- max-ageのみ指定
- ブラウザとCDNの両方にキャッシュ期間を伝えます
- s-maxageのみ指定
- CDNにのみキャッシュ期間を伝えます
- max-ageとs-maxageの両方を指定
- ブラウザにはmax-age、CDNにはs-maxageで指定されたキャッシュ期間を伝えます
注意点
GET/HEAD以外はキャッシュされない
例えばPOSTやPUTなどはキャッシュされません。毎回Functionが実行されます。
ローカルサーバでの挙動
ローカルで確認用のサーバをfirebase serve
で起動してFunctionを実行した場合、ローカルのサーバではキャッシュされませんが、cache-controlヘッダは出力されますのでmax-ageのみ指定している場合はブラウザのキャッシュが効いている可能性が高いです。
$ telnet localhost 5001 HEAD /test-f76bc/us-central1/CDNCacheTest HTTP/1.1 host: localhost HTTP/1.1 200 OK x-powered-by: Express cache-control: public, max-age=30 content-type: text/html; charset=utf-8 content-length: 77 etag: W/"4d-O015JftnB9bMeC9SgNkQhV3dzSs" date: Sat, 18 Apr 2020 10:07:01 GMT connection: close
「あれ?ローカルなのに更新されてない?」と思ったら、シフトキーを押しながら再読み込みするかキャッシュを削除してからもう一度リクエストしてみてください。