web-dev-qa-db-ja.com

paramsを介したキャッシュ無効化

本番環境でのバストをキャッシュしたいのですが、そうするためのシステムを見つけ出すために大量の時間を無駄にしないでください。私の考えは、現在のバージョン番号でcssファイルとjsファイルの最後にパラメータを適用することでした:

<link rel="stylesheet" href="base_url.com/file.css?v=1.123"/>

2つの質問:これにより、キャッシュが事実上破損しますか? paramは、これが動的コンテンツであることを示すため、paramはブラウザーにそのURLからの応答をキャッシュさせませんか?

110
Brad Herman

パラメータ?v=1.123はクエリ文字列を示すため、ブラウザは?v=1.0などからの新しいパスであると見なします。したがって、キャッシュからではなく、ファイルからロードされます。あなたが望むように。

そして、ブラウザーは、次回?v=1.123を呼び出し、そのストリングでshouldをキャッシュしても、ソースは同じままであると想定します。したがって、?v=1.124などに移動するまで、サーバーはセットアップされますが、キャッシュされたままになります。

105
Marshall

2つの質問:これにより、キャッシュが事実上破損しますか?

はい。 スタックオーバーフローでもこの方法を使用します (1日あたり数百万の訪問者と数百の異なるクライアントとプロキシのバージョンと構成を持つ)彼らは、これでさえ不十分ないくつかの奇妙なEdgeケースがあったことを覚えていますがキャッシュを破壊します。しかし、一般的な仮定はこれが機能することであり、クライアントのキャッシュを破るのに適した方法です。

Paramは、これが動的コンテンツであることを示すため、paramはブラウザーにそのURLからの応答をキャッシュさせませんか?

いいえ。パラメータはキャッシュポリシーを変更しません。サーバーから送信されたキャッシュヘッダーは引き続き適用され、サーバーが送信しない場合はブラウザーのデフォルトが適用されます。

36
Pekka 웃

実際のファイル名にバージョン番号を入れる方が安全です。これにより、複数のバージョンが同時に存在できるため、新しいバージョンを展開できます。古いバージョンを要求しているキャッシュされたHTMLページがまだ存在する場合、それらはHTMLで動作するバージョンを取得します。

インターネット上の最大のバージョン管理されたデプロイメントの1つでは、jQueryは実際のファイル名にバージョン番号を使用し、特別なサーバー側ロジックなしで複数のバージョンを安全に共存させることができます(各バージョンは異なるファイルです)。

これは、新しいページと新しいリンクファイル(必要なもの)を展開するときにキャッシュを1回破壊し、それ以降はこれらのバージョンで効果的にキャッシュできます(これも必要です)。

22
jfriend00

他の人が言ったように、クエリパラメータを使用したキャッシュの無効化は通常、Bad Idea(tm)と見なされ、長い間行われてきました。ファイル名にバージョンを反映することをお勧めします。 Html5 Boilerplate 推奨 クエリ文字列を使用するなど。

とはいえ、情報源を引用した私が見た勧告のうち、すべては、Steve Soudersによる 2008記事 から知恵を得ているようです。彼の結論は、当時のプロキシの振る舞いに基づいており、最近では関連している場合と関連していない場合があります。それでも、最新の情報がない場合は、ファイル名を変更するのが安全なオプションです。

11
hashchange

クライアントがリソースをダウンロードした後、次の場合を除き、クライアントキャッシュから他のすべての応答が提供されます。

  1. vパラメーターが更新されます。
  2. クライアントはキャッシュをクリアします
9
ncremins

一般的にはこれで問題ありませんが、要求パラメーターを無視するように構成された中間キャッシュ(プロキシ)がある場合、これが機能しない可能性があります。

たとえば、Akamai CDNを介して静的コンテンツを提供している場合、このメソッドを使用してキャッシュの無効化を防ぐためにリクエストパラメーターを無視するように構成できます。

6
Ken Liu

キャッシングの堅牢性に大きく依存します。たとえば、Squidプロキシサーバー(および他のサーバー) デフォルトはnotキャッシング クエリ文字列で提供されるURL-少なくとも、その記事が書かれたときにした。不要なキャッシュミスを引き起こす特定のユースケースを気にしない場合は、クエリパラメータを使用してください。ただし、veryこの問題を回避するファイル名ベースのキャッシュ無効化スキームを簡単に設定できます。

5
Bobby Jack

2つの手法(クエリ文字列とファイル名)の比較を見つけました here

クエリ文字列としてのバージョンには2つの問題があります。

第1に、それは常にキャッシュを実装するブラウザであるとは限りません。特定の(おそらく古い)プロキシは、キャッシュ動作に関してクエリ文字列を無視すると言われています。

第二に、複数のフロントエンドサーバーや複数のバックエンドサーバーがある特定のより複雑な展開シナリオでは、アップグレードは瞬時ではありません。アセットの古いバージョンと新しいバージョンの両方を同時に提供できる必要があります。たとえば、Google App Engineを使用する際にこれがどのように影響するかを確認してください。

5
user

別の同様のアプローチは、 htaccessmod_rewrite を使用して、ファイルを提供するときにパスの一部を無視することです。キャッシュされないインデックスページは、ファイルへの最新のパスを参照します。

開発の観点からは、バージョン番号にparamsを使用するのと同じくらい簡単ですが、ファイル名のアプローチと同じくらい堅牢です。

バージョン番号のパスの無視された部分を使用すると、サーバーはそれを無視し、キャッシュされていないファイルを提供します。

1.2.3/css/styles.cssは、css/styles.cssと同じファイルを提供します。これは、最初のディレクトリが削除され、htaccessファイルによって無視されるためです

バージョン管理されたファイルを含める

<?php
  $version = "1.2.3";
?>

<html>
  <head>
    <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" />
    <link rel="stylesheet" type="text/css" href="<?php echo $version ?>/css/styles.css">
  </head>
  <body>
    <script src="<?php echo $version ?>/js/main.js"></script>
  </body>
</html>

このアプローチは、インデックスページのキャッシュを無効にする必要があることを意味することに注意してください- <meta>タグを使用してすべてのブラウザでキャッシュをオフにしますか?

.htaccessファイル

RewriteEngine On

# if you're requesting a file that exists, do nothing
RewriteCond %{REQUEST_FILENAME} !-f 
# likewise if a directory that exists, do nothing
RewriteCond %{REQUEST_FILENAME} !-d 

# otherwise, rewrite foo/bar/baz to bar/baz - ignore the first directory
RewriteRule ^[^/]+/(.+)$ $1 [L] 

URLの書き換えを許可するサーバープラットフォームであれば、同じアプローチを取ることができます。

mod_rewrite-/#!/を除くクエリ文字列にディレクトリを書き換える

...インデックスページ/サイトエントリポイントのキャッシュ無効化が必要な場合は、常に JavaSriptを使用 で更新できます。

4
alexanderbird
<script type="text/javascript">
// front end cache bust

var cacheBust = ['js/StrUtil.js', 'js/protos.common.js', 'js/conf.js', 'bootstrap_ECP/js/init.js'];   
for (i=0; i < cacheBust.length; i++){
     var el = document.createElement('script');
     el.src = cacheBust[i]+"?v=" + Math.random();
     document.getElementsByTagName('head')[0].appendChild(el);
}
</script> 
2
Conete Cristian

これが外部JSファイルの挿入に役立つことを願っています

<script type="text/javascript"> 
var cachebuster = Math.round(new Date().getTime() / 1000); 
document.write('<scr'+'ipt type="text/javascript" src="external.js?cb=' +cachebuster+'"></scr' + 'ipt>');
</script>

ソース- JavaScriptのキャッシュ無効化コード

0
Vinit Kadkol
 <script>
    var storedSrcElements = [
         "js/exampleFile.js",
         "js/sampleFile.js",
         "css/style.css"
          ];

    var head= document.getElementsByTagName('head')[0];
    var script;
    var link;
    var versionNumberNew = 4.6;

    for(i=0;i<storedSrcElements.length;i++){
     script= document.createElement('script');
     script.type= 'text/javascript';
     script.src= storedSrcElements[i] + "?" + versionNumberNew;
     head.appendChild(script);
    }     


     </script> 


       ### Change the version number  (versionNumberNew) when you want the new files to be loaded  ###
0
Teja