私は自分のウェブサイトのアセットをキャッシュする方法にだまされており、私のものに似たほとんどのウェブサイトがクエリ文字列を使用してキャッシュをオーバーライドしていることに気付きました(例:/css/style.css?v=124942823)
その後、style.cssファイルを保存するたびに、最後に変更されたヘッダーが「更新」され、クエリ文字列が不要になることに気付きました。
だから私は疑問に思う:
なぜ多くのWebサイトが、最後に変更されたヘッダーに機能させるのではなく、「クエリ文字列」メソッドを使用するのですか?
クエリ文字列を変更するとURLが変更され、コンテンツが「新鮮」になります。
Last-modifiedヘッダーの設定を解除して、クエリ文字列を操作する必要がありますか?
いいえ。それはほとんど正しい答えですが。
Webで使用される3つの基本的なキャッシュ戦略があります。
3つすべてを説明するために、次のシナリオを検討してください。
ユーザーが初めてWebサイトにアクセスし、10ページをロードして離脱します。各ページは同じcssファイルをロードします。上記のキャッシュ戦略のそれぞれについて、いくつのリクエストが行われますか?
このシナリオでは、結果に影響するものが他にないことは明らかです。cssファイルに対する10回のリクエストは、クライアント(ブラウザ)に10回送信されます。
Last-Modified または Etag が使用されている場合、also10個のリクエストがあります。ただし、そのうちの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
本文がなく、応答が 4 Not Modified であることに注意してください。これは、そのURLに対して既に(ローカルキャッシュに)あるコンテンツがまだ新鮮であることをクライアントに伝えています。
これが最適なシナリオであると言っているわけではありません。 chrome開発者ツール のネットワークタブ)などのツールを使用すると、リクエストにかかる正確な時間を確認できます。
応答には本文がないため、転送するデータが少ないため、応答時間ははるかに短くなります。ただし、isはまだ応答です。そして、そこにisがまだリモートサーバーに接続するオーバーヘッドのすべてです。
Etagがなく、最後に変更されたヘッダーがなく、期限が切れるヘッダーのみが将来的に設定される場合-URLへの最初のアクセスのみがリモートサーバーとの通信になります。これは よく知られていますか?フロントエンドのパフォーマンス向上のためのベストプラクティス です。この場合、後続のリクエストでは、クライアントは自身のキャッシュからコンテンツを読み取り、リモートサーバーとはまったく通信しません。
これには明確なパフォーマンス上の利点があります。これは、レイテンシーが大きくなる可能性のあるモバイルデバイスで特に重要です(軽度に言えば)。
サイトがクエリ引数を使用するのは、クライアントのキャッシュを回避するためです。コンテンツが変更されると(またはサイトの新しいバージョンが公開されると)、クエリ引数が変更されるため、URLが変更されると、そのファイルのnewバージョンが要求されます。これは、ファイルを変更するたびにファイル名を変更するよりも作業が少なく便利です。ただし、問題がないわけではありません。
クエリ文字列を使用するとプロキシキャッシュが防止されます 、以下の引用では、著者はbrowser <-> proxy cache server <-> websiteからのリクエストがプロキシキャッシュを使用しないことを実証しています:
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
として処理します。これには、キャッシュの無効化にクエリパラメーターを使用する利点がすべてありますが、withoutプロキシキャッシングを無効にする問題。
Last-Modifiedヘッダーはブラウザー間で異なる方法で適用されますが、通常、ブラウザーは条件付きGET要求を発行し、キャッシュを更新する必要がある場合にサーバーが応答する必要があります。たとえば、Firefoxでは...
「Last-Modified」応答ヘッダーは、弱いバリデーターとして使用できます。 1秒の解像度しかないため、弱いと見なされます。応答に「Last-Modified」ヘッダーが存在する場合、クライアントは「If-Modified-Since」リクエストヘッダーを発行して、キャッシュされたドキュメントを検証できます。
検証要求が行われると、サーバーは通常の200 OKで検証要求と応答を無視するか、キャッシュされたコピーを使用するようブラウザーに指示するために304 Not Modifiedを返すことができます。後者の応答には、キャッシュされたドキュメントの有効期限を更新するヘッダーを含めることもできます。
タイムスタンプ(またはフィンガープリント)を設定することにより、キャッシュを更新する必要があることをブラウザに明示的に通知し、非常に長い有効期限を設定できます。
Railsアセットパイプライン( http://guides.rubyonrails.org/asset_pipeline.html )のドキュメントでは、フィンガープリントの利点が3つ挙げられていることに注意してください。クエリ文字列のタイムスタンプ:
キャッシュの詳細とベストプラクティス: https://developers.google.com/speed/docs/best-practices/caching