Netlifyのキャッシュについて詳しく調べる機会があったのでメモ。このページに全部書いてあった。Better Living Through Caching
Netlifyのキャッシュのデフォルト設定
自分で何か設定をしなくても、Netlify側でデフォルトで設定されているキャッシュ設定がある。レスポンスヘッダを見れば一目瞭然だが、設定されているのは以下。
- Cache-control
- ETag
それぞれについて見ていく。
Cache-control
デフォルトはpublic, max-age=0, must-revalidate
となっている。これの意味するところは、
- public: キャッシュ可能なコンテンツであることを示す
- max-age: キャッシュが有効とみなされる期間
- must-revalidate: リクエストのたびにオリジンサーバーにキャッシュコンテンツの陳腐化を確認する必要がある
この設定により、ブラウザはコンテンツをキャッシュすることはできるが、そのキャッシュの保存期間に関わらず、利用してよいかどうかを毎回サーバーに問い合わせて確認する必要があるという設定になる。no-store
に近い感じもするが、こちらはキャッシュ自体を許可しない。
毎回サーバーに問い合わせるならキャッシュの意味なくね?と思うかもしれないが、キャッシュが有効とみなされた場合はコンテンツをダウンロードする必要がなく、レスポンスボディをほぼ0にできる(ステータスは304 Not Modified)。
コンテンツのダウンロード時間はファイルのサイズによってはかなり長くなるので、このキャッシュ戦略は非常に意味がある(実際、体感的にも大きな差がある)。
参考:HTTP キャッシュ
ETag
では、どのような条件下でキャッシュの利用が許可されるのか、それを判断するのがETagである。
ETagはコンテンツのなんらかのパラメータにハッシュ関数を適用した値で、バージョン識別子のようなもの。
ETagが同じであればそのコンテンツは変更されていないことを意味するし、異なっていればコンテンツが更新されたことを意味する。
NetlifyサーバーからのレスポンスヘッダにはこのETagが含まれており、次回以降のリクエスト時にIf-None-MatchフィールドにETagの値をセットして送信する。
Netlifyでは、上記のCache-controlとETagの設定を組み合わせることによりコンテンツが更新(デプロイ)されるまで、ブラウザキャッシュを利用するというキャッシュ戦略がデフォルトで設定されていることになる。
参考:ETag
キャッシュ戦略の変更
上記のキャッシュ設定を変更したい場合は、リポジトリにカスタムヘッダを指定するファイルを置くことで対応する。_headers
という名前のファイルを作成し、公開ディレクトリの直下に配置すればOK。
キャッシュ設定の仕様(不具合?)
Branch DeployやPull Request作成時にプレビュー環境のビルド&デプロイが走ると、Production環境のキャッシュがクリアされる。Production環境のレスポンスに含まれるETagの値は変更されておらず、リクエストヘッダのIf-None-Matchの値とも一致しているにの関わらず、200 OKでレスポンスが返ってくる。プレビュー環境がビルドされる際に、サーバー側に保存されている他の環境のETagもクリアされている?