Webシステム全体はHTTPプロトコルの上に構築されており、HTTPキャッシュメカニズムを使用することで、サーバーの負荷を大幅に軽減するだけでなく、ページの読み込みを高速化し、ユーザーのトラフィック消費を抑えることができます。 高速な到達性とアクセスのしやすさはウェブ固有の特徴であり、キャッシング・メカニズムは長い間、サーバーやブラウザのベンダーによって広く実装されてきました。
HTTPキャッシュ入門
HTTPキャッシュについて話すとき、最初に思い浮かぶのはディスクキャッシュと304ステータスコードでしょう。 これらはブラウザがキャッシュを処理する2つのシナリオです:
- ブラウザはサーバーにキャッシュが有効かどうかを尋ね、サーバーはブラウザがキャッシュを使用していることを示す304を返します。
- リソースがまだ有効な間は、ブラウザはディスクキャッシュを直接使用します。
各状態の詳細は以下の通り:
1.キャッシュ制御
Cache-Controlは、プロキシとUAがどのキャッシュポリシーを使用しているかを示すためにHTTP応答ヘッダーで使用されます。例えば
- no-cache は、そのレスポンスが後続のリクエストに直接使われないことを意味します。
- no-storeでキャッシュを無効にします。
- プライベートからUAのみキャッシュ可能
- PUBLICは全員にキャッシュされます。
Cache-Control が cachable の場合、キャッシュ時間を指定することもできます。 これは、ブラウザが 1 日間キャッシュを直接使用できることを意味します。 もちろん、ブラウザはいつでもキャッシュを破棄する権利を持っているので、ここで一貫性の問題が発生する可能性があります。
2.エタグ
リソース自体が時々変更される場合、Cache-Controlを使用すると更新されないページがユーザーに残ります。 しかし、HTTPキャッシュも利用したい場合は、条件付きのHTTPリクエストが必要になります。
HTTPプロトコルの仕様では、ETagは「要求された変数のエンティティタグ」と定義されており、コンテンツのセマンティクスが変更されていない限り弱いエンティティ、強いエンティティはバイトが同一でなければならないことを意味し、弱いエンティティを使用することが推奨されています。
レスポンスボディがEtagフィールドを含む場合、ブラウザは次にIf-None-Matchヘッダーフィールドを持つリクエストを送るときに、そのバージョンがまだ利用可能かどうかをサーバに照会ます。サーバーがそのバージョンがまだ最新であることを発見した場合、UAにキャッシュの使用を継続するように指示する304ステータスコードを返すことができます。これはサーバー側で返される書式に似ています:Cache-Control
クライアントのクエリー更新フォーマットは以下のようになります:private
ETagが変更されていない場合、ステータス304が返されます。
3.最終更新日
ブラウザが URL を最初にリクエストしたとき、サーバ側のリターン・ステータスは 200 になり、リクエストされたリソースの内容が返されます:public
クライアントがこのURLを2回目にリクエストしたとき、ブラウザはIf-Modified-Sinceヘッダをサーバーに送信し、HTTPプロトコルに従って、ファイルがその時点以降に変更されたかどうかを尋ねます:ETag: W/"3ae83efccfc543badcd8bfb9"
サーバ側のリソースが変更されない場合、HTTP 304 ステータスコードが空のコンテンツと共に自動的に返され、転送されるデータ量が節約されます。サーバ側のコードが変更されたり、サーバが再起動されたりすると、リソースは再発行され、最初のリクエストと同様に返されます。これにより、リソースが繰り返しクライアントに発行されることがなくなるとともに、サーバが変更されたときにクライアントが最新のリソースを取得できるようになります。
注意: If-Modified-Sinceの時間がサーバーの現在時刻より遅い場合、不正なリクエストとみなされます。
4.期限切れ
指定された日時を過ぎると、そのレスポンスは時代遅れとみなされます。例: Expires:Thu, 02 Apr 2009 05:14:08 GMT
Last-Modified と組み合わせて使用する必要があります。要求されたファイルの有効性を制御するために使用され、要求されたデータが有効期間内にある場合、クライアントブラウザはサーバではなくキャッシュからデータを要求します。キャッシュ内のデータが無効または期限切れの場合、そのときだけサーバからデータを更新します。
5、最終更新日時と有効期限
Last-Modifiedフラグは帯域幅を少し節約しますが、それでもHTTPリクエストの送信を免れることはできず、Expiresと併用する必要があります。Expiresのロゴは、ブラウザが単にHTTPリクエストを送信しないようにします。例えば、ユーザがF5をしたり、更新ボタンをクリックしたりすると、Expires付きのURIであっても、同じようにHTTPリクエストが送信されます。
6.EtagとExpires
7、Last-Modified および Etag
異なるマシンへのロードバランシングによる比較の失敗を避けるため、最終更新ファイルは分散システム内の複数のマシンで一貫していなければなりません。
分散システムはできるだけEtagをオフにします(生成されるEtagはマシンごとに異なります)。
Last-Modified は ETags リクエストの http ヘッダと一緒に使われ、 サーバは最初に Last-Modified/Etag タグを生成します。
プロセスは以下の通り。
- クライアントがページをリクエストします。
- サーバーはAにLast-Modified/ETagを追加したページAを返します。
- クライアントはページを表示し、Last-Modified/ETagとともにページをキャッシュします。
- クライアントはページAを再度リクエストし、リクエスト時にサーバーが返したLast-Modified/ETagとともにサーバーに渡します。
- サーバはこのLast-ModifiedまたはETagをチェックし、クライアントからのリクエスト以降ページが変更されていないと判断し、レスポンス304と空のレスポンスボディを直接返します。
注意事項
- WebServer が Last-Modified/Etag ヘッダをクライアントに送信した後、クライアントはそれらをキャッシュします;
- 上記の値はサーバー側でチェックされ、ファイルがキャッシュされ続けるかどうかを決定します;
8. Cache-Control: max-age=seconds および Expires について
Expires = 時間、HTTP バージョン 1.0、キャッシュのロード時間、クライアントがこの時間をチェックしないようにする max-age = 秒、HTTP バージョン 1.1、リソースがローカルにキャッシュされる時間。max-age と Expires の両方が存在する場合、Cache-Control の max-age によって上書きされます。
Expiresの欠点は、返される有効期限がサーバ側の時間であるため、クライアントの時間とサーバの時間が大きく異なる場合、エラーが非常に大きくなるという問題があるため、HTTPバージョン1.1以降では、代わりにCache-Control: max-age=secondsを使用するようになりました。
Expires =max-age + "ダウンロードごとの現在のリクエスト時間"
そのため、ページが再ダウンロードされると、期限は再計算されますが、最終更新日時は変更されません。
9.ブラウザの更新
通常リロード
更新ボタンまたはショートカットキーを押すと、ブラウザの「通常の再読み込み」がトリガーされ、条件付きGETが実行されます。 Cache-Controlなどのキャッシュヘッダは無視され、If-None-Match、If-Modified- Sinceなどのヘッダは無視されます。If-None-Match、If-Modified-Since などのヘッダは無視されます。 サーバーは常に HTTP GET リクエストを受け取ります。 Chromeで更新を押すと、ブラウザは次のリクエストヘッダも表示します: Cache-Control:max-age=0
注:アドレスバーに現在のページアドレスを再入力してEnterキーを押すことも更新として扱われます。つまり、ハードディスクキャッシュの直接使用は、新しいタブまたはハイパーリンクから開いた場合にのみ確認できます。
強制リロード
ChromeでCmd+Shift+Rキーを押すと、ページ自体を含むすべてのリソースがキャッシュされない強制リロードが実行されます。 ブラウザは、条件付きのリクエスト フィールドを使用せずに HTTP リクエストを直接送信します。 Chrome で強制更新を行うには、ブラウザは次のリクエストヘッダも使用します: Cache-Control: no-cache Pragma: no-cache
キャッシュされた静的ファイルを無効にする方法
一般的にページ上の多くのjsファイルやcssファイルを参照し、要求がされているとブラウザのリソースにキャッシュされると無効ではありませんが、この時間は、バグが修正または新しいものをリリースする必要がある必要が見つかりました、どのように行うのですか?一部の人々は、良い、または要求でブラウザをリフレッシュするために強制的に304を返さない、直接新しいリソースの内容に戻りますが、これは良い操作ではありませんが、1つは、ユーザーがリフレッシュまたはキャッシュをクリアするために強制的に知らないかもしれないということです、2番目はちょうど新しいコンテンツとキャッシュに戻るには、最初のユーザーの要求の後に新しいコンテンツを公開したいですが、バックはまだキャッシュに行くつもりです。CDNは、一般的に使用され、各リリースの後、あなたは非常に面倒なCDNのキャッシュをクリーンアップする必要があります。実際には、最も簡単な方法の一つは、これらの静的リソースを参照することですバージョン番号、同様のときに追加することができます.../js/index.js?v=1.0このような、コンテンツを変更する場合は、単にバージョン番号を変更することができ、ブラウザは自然に新しいコンテンツを取得します。