ファイルキャッシュ: クエリ文字列と Last-Modified の違いは? 質問する

ファイルキャッシュ: クエリ文字列と Last-Modified の違いは? 質問する

私は自分のウェブサイトのアセットをキャッシュする方法をあれこれ試していたところ、私のウェブサイトに似たほとんどのウェブサイトがキャッシュを上書きするためにクエリ文字列を使用していることに気付きました (例: /css/style.css?v=124942823)

その後、style.css ファイルを保存するたびに、最後に変更されたヘッダーが「更新」され、クエリ文字列が不要になっていることに気付きました。

そこで私は疑問に思う。

  • 多くの Web サイトが、last-modified ヘッダーをそのまま機能させるのではなく、「クエリ文字列」方式を使用するのはなぜでしょうか?
  • Last-modified ヘッダーを設定解除して、クエリ文字列のみで作業する必要がありますか? (これには特別な利点がありますか?)

ベストアンサー1

要約

多くの Web サイトが、last-modified ヘッダーをそのまま機能させるのではなく、「クエリ文字列」方式を使用するのはなぜでしょうか?

クエリ文字列を変更すると URL が変更され、コンテンツが「最新」であることが保証されます。

Last-modified ヘッダーを設定解除して、クエリ文字列のみで作業する必要がありますか?

いいえ。ほとんど正しい答え。


Web で使用される基本的なキャッシュ戦略は 3 つあります。

  • キャッシュなし、またはキャッシュが無効
  • 検証/条件付きリクエストの使用
  • 永遠にキャッシュ

これら 3 つを説明するために、次のシナリオを考えてみましょう。

ユーザーが初めて Web サイトにアクセスし、10 ページを読み込んで離脱します。各ページは同じ CSS ファイルを読み込みます。上記の各キャッシュ戦略では、リクエストはいくつ作成されますか?

キャッシュなし: 10 リクエスト

このシナリオでは、結果に影響を与えるものは他に何もないことは明らかであり、CSS ファイルに対する 10 回のリクエストは、クライアント (ブラウザー) に 10 回送信されることになります。

利点

  • 常に新鮮なコンテンツ
  • 労力や管理は不要

デメリット

  • 最も効率が悪い、コンテンツは常に転送される

検証リクエスト: 10 件のリクエスト

もし最終更新日またはエタグ使用されると、またリクエストは 10 回です。ただし、そのうち 9 回はヘッダーのみで、本体は転送されません。クライアントは条件付きリクエストを使用して、すでに持っているものの再ダウンロードを回避します。このサイトの CSS ファイルを例に挙げます。

ファイルが初めて要求されると、次のことが起こります。

$ curl -i http://cdn.sstatic.net/stackoverflow/all.css
HTTP/1.1 200 OK
Server: cloudflare-nginx
Date: Mon, 12 May 2014 07:38:31 GMT
Content-Type: text/css
Connection: keep-alive
Set-Cookie: __cfduid=d3fa9eddf76d614f83603a42f3e552f961399880311549; expires=Mon, 23-Dec-2019 23:50:00 GMT; path=/; domain=.sstatic.net; HttpOnly
Cache-Control: public, max-age=604800
Last-Modified: Wed, 30 Apr 2014 22:09:37 GMT
ETag: "8026e7dfc064cf1:0"
Vary: Accept-Encoding
CF-Cache-Status: HIT
Expires: Mon, 19 May 2014 07:38:31 GMT
CF-RAY: 1294f50b2d6b08de-CDG
.avatar-change:hover{backgro.....Some KB of content

同じ URL に対する後続のリクエストは次のようになります。

$ curl -i -H "If-Modified-Since:Wed, 30 Apr 2014 22:09:37 GMT" http://cdn.sstatic.net/stackoverflow/all.css
HTTP/1.1 304 Not Modified
Server: cloudflare-nginx
Date: Mon, 12 May 2014 07:40:11 GMT
Content-Type: text/css
Connection: keep-alive
Set-Cookie: __cfduid=d0cc5afd385060dd8ba26265f0ebf40f81399880411024; expires=Mon, 23-Dec-2019 23:50:00 GMT; path=/; domain=.sstatic.net; HttpOnly
Cache-Control: public, max-age=604800
Last-Modified: Wed, 30 Apr 2014 22:09:37 GMT
ETag: "8026e7dfc064cf1:0"
Vary: Accept-Encoding
CF-Cache-Status: HIT
Expires: Mon, 19 May 2014 07:40:11 GMT
CF-RAY: 1294f778e75d04a3-CDG

本文はなく、応答は304 変更されていませんこれは、クライアントに、その URL のコンテンツ (ローカル キャッシュ内) がまだ新しいことを伝えます。

これは最適なシナリオとは言えません。Chrome 開発者ツールのネットワークタブリクエストにかかった時間と、その処理内容を正確に確認できます。

ここに画像の説明を入力してください

レスポンスには本体がないので、転送するデータが少なくなり、レスポンス時間が大幅に短縮されます。しかし、まだ応答があります。そしてそこにリモート サーバーに接続するためのオーバーヘッドはすべて残ります。

利点

  • 常に新鮮なコンテンツ
  • 「完全」リクエストが 1 つだけ送信されました
  • 9つのリクエストはヘッダーのみを含むため、はるかにスリムです
  • もっと効率的

デメリット

  • 依然として最大数のリクエストを発行する
  • DNSルックアップは依然として発生する
  • リモートサーバーへの接続を確立する必要があります
  • オフラインでは動作しません
  • サーバーの設定が必要な場合があります

永久キャッシュ: 1 リクエスト

ETagsや最終更新ヘッダーがなく、有効期限ヘッダーだけが遠い将来に設定されている場合は、URLへの最初のアクセスのみがリモートサーバーとの通信になります。これはよく知られている?フロントエンドのパフォーマンスを向上させるベストプラクティスこの場合、後続のリクエストではクライアントは自身のキャッシュからコンテンツを読み取り、リモート サーバーとはまったく通信しません。

これには明らかなパフォーマンス上の利点があり、これは特に、レイテンシが大きくなる可能性があるモバイル デバイスでは重要です (控えめに言っても)。

利点

  • 最も効率的で、コンテンツは一度だけ転送されます

デメリット

  • URLしなければならない既存の訪問者が古いキャッシュバージョンを読み込むのを防ぐための変更
  • セットアップ/管理に最も手間がかかる

キャッシュバスティングにクエリ文字列を使用しない

サイトがクエリ引数を使用するのは、クライアントのキャッシュを回避するためです。コンテンツが変更された場合(またはサイトの新しいバージョンが公開された場合)、クエリ引数は変更され、新しいURLが変更されたため、そのファイルのバージョンが要求されます。これは、変更されるたびにファイルの名前を変更するよりも手間がかからず便利ですが、問題がないわけではありません。

クエリ文字列を使用するとプロキシキャッシュが防止されます以下の引用では、著者はブラウザ<->プロキシ キャッシュ サーバー<->Web サイトからのリクエストではプロキシ キャッシュが使用されないことを示しています。

mylogo.gif?v=1.2 を 2 回ロードすると (その間にキャッシュをクリアします)、次のヘッダーが生成されます。

>> GET http://stevesouders.com/mylogo.gif?v=1.2 HTTP/1.1
<< HTTP/1.0 200 OK
<< Date: Sat, 23 Aug 2008 00:19:34 GMT
<< Expires: Tue, 21 Aug 2018 00:19:34 GMT
<< X-Cache: MISS from someserver.com
<< X-Cache-Lookup: MISS from someserver.com

>> GET http://stevesouders.com/mylogo.gif?v=1.2 HTTP/1.1
<< HTTP/1.0 200 OK
<< Date: Sat, 23 Aug 2008 00:19:47 GMT
<< Expires: Tue, 21 Aug 2018 00:19:47 GMT
<< X-Cache: MISS from someserver.com
<< X-Cache-Lookup: MISS from someserver.com

ここでは、2 番目の応答がプロキシによって提供されなかったことは明らかです。キャッシュ応答ヘッダーには MISS と表示され、Date と Expires の値が変更され、stevesouders.com アクセス ログを末尾に追跡すると 2 つのヒットが表示されます。

これを軽視すべきではありません。物理的に地球の反対側にある Web サイトにアクセスする場合、応答時間が非常に遅くなる可能性があります。ルート上にあるプロキシ サーバーから応答を取得すると、Web サイトが使用可能かどうかが変わります。永久キャッシュ リソースの場合は、URL の最初の読み込みが遅くなることを意味し、検証要求を使用する場合は、サイト全体が遅くなることを意味します。

代わりにバージョン管理資産

「最善の」解決策は、コンテンツが変更されるたびに URL も変更されるようにファイルをバージョン管理することです。通常、これはビルド プロセスの一部として自動化されます。

しかし、それに対する妥協策として、書き換えルールを実装することが挙げられます。のような

# ------------------------------------------------------------------------------
# | Filename-based cache busting                                               |
# ------------------------------------------------------------------------------

# If you're not using a build process to manage your filename version revving,
# you might want to consider enabling the following directives to route all
# requests such as `/css/style.12345.css` to `/css/style.css`.

# To understand why this is important and a better idea than `*.css?v231`, read:
# http://stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring

<IfModule mod_rewrite.c>
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpe?g|gif)$ $1.$3 [L]
</IfModule>

この方法では、リクエストはfoo.123.cssサーバーによって次のように処理されますfoo.css。これは、キャッシュバスティングにクエリパラメータを使用する利点をすべて備えていますが、それなしプロキシ キャッシュを無効にする問題。

おすすめ記事