LoginSignup
7
7

More than 1 year has passed since last update.

HTTPキャッシュとRails

Last updated at Posted at 2022-12-15

HTTPにはキャッシュの機能がありますが、Rails標準でも意外なところまで組み付けてあったりします。

記事の守備範囲

この記事では、Railsが動的に生成する箇所のキャッシュを中心に考えます。事前に生成して、送信にRailsが直接関与しないこともあるアセット類については、考慮の対象から除外します。

HTTPのキャッシュ

まず、HTTPのキャッシュには大きく分けて2通りの役割があります。

  • キャッシュがある状態で全く通信を行わず、キャッシュした結果をそのまま利用する
  • キャッシュのある状態で更新確認のための通信を行い、変化がなければ再利用する

そして、キャッシュされたものには2つの状態があります。

  • fresh…キャッシュを信じて、通信せずに利用して問題ないことを示しています。
  • stale…キャッシュが古くなっている、という状況です。

Cache-Controlヘッダ

HTTPキャッシュの指示のために、Cache-ControlというHTTPヘッダが存在します。詳細はMDNに譲りますが、ある程度まとめておきます。

  • no-store…一切のキャッシュ禁止
  • must-revalidate…staleなキャッシュを使う前に更新確認を行う
  • max-age…キャッシュがfreshである期間の設定
  • no-cache…最初からstaleなキャッシュであるとの宣言(must-revalidate, max-age=0と同様)。キャッシュしないという意味ではない
  • private…キャッシュが共有不可能であることを示す。
  • public‥キャッシュが共有可能であることを示す。
  • なお、privatepublicも入れなかった場合、どちらで扱われるかは他のディレクティブの設定によります。ただし、Railsから使う場合は「publicを指定しなければprivateが自動で入る」という動作が組んであるので、デフォルトを気にする必要はあまりありません。

Rails標準の動作

Rails標準では、以下のように動作します。

  • ビューの中身からETagを生成
  • レスポンスはmust-revalidate, max-age=0, privateで送信
  • 次回にIf-None-MatchでETagが正しかった場合、レスポンス本体は返さず304 Not Modifiedで応答

ということで、同じレスポンスを返したい場合、内容の転送負荷は削減されることになります。ビューを生成してからETagでチェックするため、不必要にキャッシュが残る心配はないのですが、ビュー処理の負荷は消えないことになります。

シナリオ別の設定

一定時間キャッシュを残したい

キャッシュを一定時間残して、その間はリクエストも行わないようにしたい、という場合、コントローラーでexpires_inというメソッドを使えます。

なお、その時間内はキャッシュの更新がされませんので、「残ってしまってもかまわない状況で使う」、「元データが変更になった際にはURLごと変更する」、「一定時間ごとにデータが変わる状況で、変わる時点までのキャッシュを行う」など、何かしらの戦略が必要となります。

一切キャッシュさせない

これも、Rails 7ではno_storeメソッドが登場していますが、それ以前のバージョンではrequest.cache_control.replace(no_store: true)のようにデータを書き換える必要があります。

Not Modified時の処理負荷を軽減したい

最終更新日時や特定の値などで、ビュー全体を描画しなくてもキャッシュの有効無効を判定できる場合、stale?というメソッドが有用です。

:etag:last_modifiedなどに条件を設定して、それらの条件をリクエストと照合して、レスポンスボディ不要となれば、304 Not Modifiedのレスポンスを生成した上でfalseを返します。return if stale?のようにしてコントローラーから抜けてしまえば、それ以降の処理は不要となります。

外部リンク

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7