web-dev-qa-db-ja.com

「Cache-Control:max-age = 0、no-cache」が、ブラウザはサーバークエリをバイパスします(そしてキャッシュにヒットします)?

Chrome 40(とても素敵でモダンなもの)を使用しています。

Cache-Control: max-age=0, no-cacheはすべてのページに設定されているため、最初にサーバーでチェックして304 Not Modified応答を受け取った場合にのみ、ブラウザーはキャッシュから何かを使用することを期待しています。

ただし、戻るボタンを押すと、ブラウザはサーバーに確認せずに独自のキャッシュをヒットします。

戻るボタンで到達したように、新しいタブで同じページを開くと、サーバーで確認します(変更が加えられたときに303 See Other応答を受け取ります)。

Chrome開発者ツールの[ネットワーク]タブからの2つの異なるケースの出力を示す以下のスクリーンキャプチャを参照してください。

max-age=0, no-cacheに代わる軽量の代替としてno-storeを使用して、ユーザーが[戻る]ボタンを介して古いデータを表示したくない場合(ただし、データが貴重でキャッシュできる場合) 。

no-cache(SOの here および here を参照)の私の理解は、ブラウザーは常にすべての応答を再検証する必要があるということです。では、なぜ戻るボタンを使用するときにChromeしないのですか?

no-storeのみがオプションですか?


戻るボタンを押したときの200応答(キャッシュから):

enter image description here

303新しいタブで同じページをリクエストしたときの応答:

enter image description here

16
George Hawkins

From http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1

キャッシュなし

No-cacheディレクティブでフィールド名が指定されていない場合、キャッシュは、Originサーバーとの再検証に成功せずに後続の要求を満たすために応答を使用してはなりません。これにより、Originサーバーは、クライアントのリクエストに対して古い応答を返すように設定されたキャッシュによってもキャッシュを防ぐことができます。

No-cacheディレクティブが1つ以上のフィールド名を指定する場合、キャッシュは、キャッシュに関する他の制限に従って、応答を使用して後続の要求を満たすことができます(MAY)。ただし、指定されたフィールド名は、Originサーバーとの再検証が成功しない限り、後続のリクエストへの応答で送信してはなりません(MUST NOT)。これにより、Originサーバーは、応答内の特定のヘッダーフィールドの再利用を防ぎながら、残りの応答のキャッシュを許可します。

名前が意味することを除いて、no-cacheは、応答をキャッシュに保存してはならないことを要求しません。キャッシュされた応答は、再検証せずにsubsequent要求を処理するために再利用してはならないことのみを指定しているため、must-revalidate, max-age=0の省略形です。

subequentリクエストとして何を修飾するかはブラウザー次第であり、戻るボタンを使用することはそうではありません。この動作は、ブラウザーエンジンによって異なります。

no-storeは、後続の要求だけでなく、すべての要求に対してキャッシュされた応答を使用することを禁止します。

no-storeを使用しても、RFCは実際にはクライアントが履歴バッファーで使用するために応答を保存することを許可していることに注意してください。つまり、no-storeが指定されている場合でも、クライアントはキャッシュされた応答を引き続き使用できます。

後者の動作は、ページがブラウザーの履歴に元のページタイトルで記録されている場合を対象としています。別のユースケースは、さまざまなモバイルブラウザーの動作で、ユーザーが中止する可能性があるため、次のページが完全に読み込まれるまで前のページを破棄しません。

戻るボタンの動作に関する説明: http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13によると、キャッシュヘッダーの影響を受けません.13

ユーザーエージェントには、「戻る」ボタンや履歴リストなどの履歴メカニズムがあり、これらを使用して、セッションの早い段階で取得したエンティティを再表示できます。

履歴のメカニズムとキャッシュは異なります。特に、履歴メカニズムは、リソースの現在の状態の意味的に透過的なビューを表示しようとすべきではありません。むしろ、履歴メカニズムは、リソースが取得されたときにユーザーが見たものを正確に表示することを目的としています。

デフォルトでは、有効期限は履歴メカニズムに適用されません。エンティティがまだストレージにある場合、ユーザーが期限切れの履歴ドキュメントを更新するようにエージェントを明確に設定していない限り、エンティティが期限切れになっても履歴メカニズムはそれを表示する必要があります。

つまり、[戻る]ボタンを使用するときにキャッシュコントロールヘッダーを無視することをお勧めします。ブラウザが期限切れの有効期限を遵守するか、ブラウザキャッシュだけでなく履歴にもno-storeディレクティブを適用する場合、実際にはすでにその推奨事項から逸脱しています。

解決方法:
あなたはできません。ユーザーが以前にアクセスしたページに戻っている場合、ほとんどのブラウザーはビューポートの復元を試みます。 AJAXなどの遅延メカニズムを使用して、これがユーザーがページを離れる前の元の動作であった場合はコンテンツを更新できますが、そうでない場合はコンテンツを変更することさえできません。

24
Ext3h

キャッシュなしヘッダーの完全な古いセットを使用してみましたか?

<meta http-equiv="cache-control" content="max-age=0" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
<meta http-equiv="pragma" content="no-cache" />

"pushState" Webを実行していない限り、これは常に機能するようです。

1
Ingmars

これは、Chromeの[戻る]ボタンを使用した場合の既知の「癖」のように見えます。この問題のバグレポートには、ここで問題に関する適切な議論があります。

https://code.google.com/p/chromium/issues/detail?id=28035

悲しいことに、ほとんどの人は代わりにno-storeを使用するようになったようです。

しかし、ほとんどのユーザーは、戻るボタンを使用してページ全体を更新しないという経験に慣れていることを期待しています。ほとんどのAngularまたはBackboneアプリ自体について考えている場合、ページではなくコンテンツのみを更新します。これを念頭に置いて、彼らが戻ってくるのはそれほど予想外ではないかもしれません。

1
JodiMiddleton