web-dev-qa-db-ja.com

ブラウザにキャッシュされたCSS/JSファイルを強制的にリロードさせる方法は?

私はいくつかのブラウザ(特にFirefoxとOpera)が .css .js ファイルのキャッシュされたコピーを使うことに非常に熱心であることに気づいた、ブラウザセッションの間でさえ。これらのファイルのいずれかを更新しても、ユーザーのブラウザがキャッシュコピーを使用し続けると、問題が発生します。

問題は、ファイルが変更されたときにユーザーのブラウザにそのファイルを強制的に再ロードさせる最もエレガントな方法は何ですか?

理想的には、このソリューションでは、ページにアクセスするたびにブラウザにファイルを強制的に再ロードさせることはありません。私は答えとして私自身の解決策を投稿するつもりですが、誰かがより良い解決策を持っているのであれば私は興味がありますそして私はあなたの投票を決定させます。

更新:

しばらくここで議論を許した後に、 John Millikin および da5id の提案が有用であることがわかりました。これには、次のような用語があります。 自動バージョン管理

以下に新しい答えを投稿しました。これは私の最初の解決策とJohnの提案を組み合わせたものです。

SCdF によって提案されたもう一つのアイデアは、偽のクエリ文字列をファイルに追加することです。 (タイムスタンプを偽の問い合わせ文字列として自動的に使用するPythonコードの一部は pi によって送信されました。)ただし、ブラウザがクエリ文字列を使用してファイルをキャッシュするかどうかについては、いくつかの議論があります。 (覚えておいて、私たちはブラウザがファイルをキャッシュして将来の訪問の際にそれを使うことを望んでいます。ファイルが変更されたときだけ再びそれをフェッチすることを望みます。)

偽のクエリ文字列で何が起こるかは明確ではないので、私はその答えを受け入れていません。

932
Kip

更新: John Millikin および da5id からの提案を組み込むように書き直されました。この解決策はPHPで書かれていますが、他の言語にも容易に適応できるはずです。

更新2: Nick Johnsonからのコメントの組み込み 元の.htaccess regexはjson-1.3.jsのようなファイルで問題を起こす可能性があること。解決策は、末尾に正確に10桁ある場合にのみ書き換えることです。 (10桁は2001年9月9日から11月20日までのすべてのタイムスタンプをカバーするためです。)

まず、.htaccessで次の書き換え規則を使用します。

RewriteEngine on
RewriteRule ^(.*)\.[\d]{10}\.(css|js)$ $1.$2 [L]

それでは、次のPHP関数を書きます。

/**
 *  Given a file, i.e. /css/base.css, replaces it with a string containing the
 *  file's mtime, i.e. /css/base.1221534296.css.
 *  
 *  @param $file  The file to be loaded.  Must be an absolute path (i.e.
 *                starting with slash).
 */
function auto_version($file)
{
  if(strpos($file, '/') !== 0 || !file_exists($_SERVER['DOCUMENT_ROOT'] . $file))
    return $file;

  $mtime = filemtime($_SERVER['DOCUMENT_ROOT'] . $file);
  return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $file);
}

今、あなたがあなたのCSSを含むところはどこでも、これからそれを変えてください:

<link rel="stylesheet" href="/css/base.css" type="text/css" />

これに:

<link rel="stylesheet" href="<?php echo auto_version('/css/base.css'); ?>" type="text/css" />

こうすれば、リンクタグを再度修正する必要がなくなり、ユーザーには常に最新のCSSが表示されます。ブラウザはCSSファイルをキャッシュできますが、CSSに変更を加えるとブラウザはこれを新しいURLとして認識するため、キャッシュされたコピーは使用されません。

これは画像、ファビコン、そしてJavaScriptでも動作します。動的に生成されないものは基本的に何でも。

438
Kip

簡単なクライアントサイドテクニック

一般に、キャッシュは有効です。したがって、Webサイトを開発するときに問題を自分で解決するのか、それとも本番環境でキャッシュを制御しようとしているのかに応じて、2つの手法があります。

あなたのウェブサイトへの一般の訪問者はあなたがそのサイトを開発しているときにあなたが経験しているのと同じ経験を持つことはないでしょう。平均的な訪問者はあまり頻繁にサイトに来ないので(たぶん月に数回、あなたがグーグルまたはhi5ネットワークでなければ)、彼らはあなたのファイルをキャッシュに入れる可能性が低く、それで十分かもしれません。ブラウザに新しいバージョンを強制する場合は、いつでもクエリ文字列をリクエストに追加し、大きな変更を加えるときにバージョン番号を上げることができます。

<script src="/myJavascript.js?version=4"></script>

これにより、全員が新しいファイルを取得できます。ブラウザがファイルのURLを調べて、キャッシュ内にコピーがあるかどうかを判断するためです。サーバがクエリ文字列に対して何もしないように設定されていない場合、それは無視されますが、名前はブラウザにとって新しいファイルのように見えます。

一方、Webサイトを開発している場合は、開発バージョンに変更を保存するたびにバージョン番号を変更したくはありません。それは面倒です。

そのため、サイトを開発している間は、クエリ文字列パラメータを自動的に生成することをお勧めします。

<!-- Development version: -->
<script>document.write('<script src="/myJavascript.js?dev=' + Math.floor(Math.random() * 100) + '"\><\/script>');</script>

リクエストにクエリ文字列を追加することは、リソースをバージョン管理するための良い方法ですが、単純なWebサイトではこれは不要な場合があります。そして、覚えておいて、キャッシングは良いことです。

ブラウザがファイルをキャッシュに保存することについて必ずしも気難しいとは限らないことも注目に値します。ブラウザにはこの種のことに対するポリシーがあり、それらは通常HTTP仕様で定められた規則に従って機能しています。ブラウザがサーバに要求を出すと、応答の一部はEXPIRESヘッダです。ブラウザにキャッシュに保持する期間をブラウザに指示する日付です。次にブラウザが同じファイルに対する要求に遭遇したとき、それはキャッシュにコピーがあることを見て、それが使用されるべきかどうか決定するためにEXPIRES日付を調べます。

信じられないかもしれませんが、ブラウザのキャッシュを非常に永続的にしているのは実際にはサーバーです。あなたはあなたのサーバー設定を調整し、EXPIRESヘッダを変更することができますが、私が上で書いた小さなテクニックはおそらくあなたがそれに取り組むためのはるかに簡単な方法です。キャッシュは有効なので、通常はその日付をずっと未来に設定し(「Far-future Expiresヘッダー」)、上記の手法を使用して強制的に変更します。

HTTPに関するより多くの情報やこれらの要求がどのように行われるかに興味があるなら、良い本はSteve Soudersによる "High Performance Web Sites"です。それは主題への非常に良い紹介です。

179
keparo

Apacheのグーグルの mod_pagespeed プラグインはあなたのために自動バージョン管理をするでしょう。本当に滑りやすいです。

Webサーバーから出る途中でHTMLを解析し(PHP、Rails、python、静的HTMLなどに対応)、CSS、JS、画像ファイルへのリンクを書き換えてIDコードを含めます。それはそれらを非常に長いキャッシュ制御で修正されたURLでファイルを提供します。ファイルが変更されると自動的にURLが変更されるため、ブラウザはそれらを再取得する必要があります。基本的には動作しますが、コードを変更することはありません。それは出て行く途中であなたのコードも縮小するでしょう。

112
Leopd

バージョンを手動で変更する代わりに、実際のCSSファイルのMD5ハッシュを使用することをお勧めします。

だからあなたのURLはのようなものになります

http://mysite.com/css/[md5_hash_here]/style.css

それでも、書き換え規則を使用してハッシュを削除することはできますが、URLが同じであればファイルは変更されないことを意味するため、キャッシュポリシーを "永久キャッシュ"に設定できるという利点があります。

その後、ファイルのハッシュを計算してタグを更新する簡単なシェルスクリプトを作成できます(含めるために別のファイルに移動することをお勧めします)。

CSSが変わるたびにそのスクリプトを実行するだけでいいのです。ファイルが変更された場合にのみ、ブラウザはファイルをリロードします。編集して元に戻しても、訪問者が再ダウンロードしないようにするためにどのバージョンに戻る必要があるかを判断するのに苦労することはありません。

90
levik

なぜこのソリューションを実装するのに苦労しているのかわからない。

ファイルの変更されたタイムスタンプを取得し、それをファイルへのクエリ文字列として追加する場合に必要なことはすべて

PHPでは、次のようにします。

<link href="mycss.css?v=<?= filemtime('mycss.css') ?>" rel="stylesheet">

filemtimeはファイル修正タイムスタンプを返すPHP関数です。

61
Phantom007

?foo=1234をcss/jsインポートの最後に置くだけで、1234を好きなものに変更できます。例としてSO htmlソースをご覧ください。

そこにあるアイデアは?とにかくパラメータはリクエストで破棄/無視され、新しいバージョンをロールアウトするときにその番号を変更できます。


注:これがキャッシングにどのように影響するかについて、いくつかの議論があります。一般的な要点は、パラメータの有無にかかわらずGETリクエストはキャッシュ可能であるため、上記の解決策が機能することです。

ただし、仕様のその部分を遵守するかどうか、およびユーザーが使用するブラウザを決定するかどうかは、Webサーバーに委ねられています。

51
SCdF

私はこれを「自動バージョン管理」と呼んでいます。最も一般的な方法は、静的ファイルのmtimeをURLのどこかに含め、書き換えハンドラまたはURL confsを使用して削除することです。

また見なさい:

39
John Millikin

30ほどの既存の回答は、2008年頃のWebサイトにとって素晴らしいアドバイスです。ただし、最新の単一ページアプリケーション(SPA)については、いくつかの基本的な前提を再考するときがあります。具体的には、 Webサーバーがファイルの単一の最新バージョンのみを提供することが望ましい。

あなたがブラウザにロードされたSPAのバージョンMを持っているユーザーを想像してください:

  1. CDパイプラインは、アプリケーションの新しいバージョンNをサーバーにデプロイします
  2. SPA内を移動し、XHRをサーバーに送信して/some.template を取得します。
    • (ブラウザはページを更新していないので、バージョンMを実行しています。)
  3. サーバーは/some.templateの内容で応答します—テンプレートのバージョンMまたはNを返しますか?

/some.templateの形式がバージョン間で変更された場合MN(またはファイルの名前が変更されたなど)おそらく、古いバージョンを実行しているブラウザに送信されるテンプレートのバージョンNは必要ありませんM the parser。†

次の2つの条件が満たされると、Webアプリはこの問題に遭遇します。

  • リソースは、最初のページのロード後、非同期に要求されます
  • アプリのロジックは、リソースコンテンツに関するもの(将来のバージョンで変更される可能性がある)を想定しています

アプリが複数のバージョンを並行して提供する必要がある場合、キャッシングと「リロード」の解決は簡単になります:

  1. すべてのサイトファイルをバージョン付きディレクトリにインストールします:/v<release_tag_1>/…files…/v<release_tag_2>/…files…
  2. ブラウザがファイルを永久にキャッシュできるようにHTTPヘッダーを設定します
    • (さらに良いことに、すべてをCDNに入れます)
  3. すべての<script>および<link>タグなどを更新して、バージョン管理されたディレクトリのいずれかでそのファイルを指すようにします

サーバー側またはクライアント側のコードのすべてのURLに対してURLビルダーを呼び出す必要があるため、この最後の手順は難しいように思えます。または、 <base>タグ を巧みに使用して、現在のバージョンを1か所で変更することもできます。

†これを回避する1つの方法は、新しいバージョンがリリースされたときにブラウザにすべてを強制的にリロードさせることを積極的に行うことです。ただし、進行中の操作を完了するために、少なくとも2つのバージョン(v-currentとv-previous)を並行してサポートするのが最も簡単な場合があります。

24
Michael Kropat

Foo.cssを使用しないでください?version = 1!ブラウザはGET変数でURLをキャッシュすることになっていません。 http://www.thinkvitamin.com/features/webapps/serving-javascript-fast によると、IEとFirefoxはこれを無視しますが、OperaとSafariは無視します。代わりに、foo.v1234.cssを使い、書き換え規則を使ってバージョン番号を取り除いてください。

14
airrob

RewriteRuleは、最後にドット表記法のバージョン管理を含むjsまたはcssファイルのための小さなアップデートを必要とします。例えば。 json-1.3.js.

正規表現so .numberにドット否定クラス[^。]を追加しました。無視されます。

RewriteRule ^(.*)\.[^.][\d]+\.(css|js)$ $1.$2 [L]
10
Nick Johnson

ASP.NET 4.5以降では スクリプトバンドリング を使用できます。

リクエストhttp://localhost/MvcBM_time/bundles/AllMyScripts?v=r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81はバンドルAllMyScriptsに対するもので、クエリ文字列ペアv = r0sLDicvP58AIXN_mc3QdyVvVj5euZNzdsa2N1PKvb81を含みます。クエリ文字列vには、キャッシュに使用される一意の識別子である値トークンがあります。バンドルが変更されない限り、ASP.NETアプリケーションはこのトークンを使用してAllMyScriptsバンドルを要求します。バンドル内のファイルが変更された場合、ASP.NET最適化フレームワークは新しいトークンを生成し、ブラウザがそのバンドルを要求したときに最新のバンドルが取得されるようにします。

縮小による初回のページロードでのパフォーマンスの向上など、バンドリングには他にも利点があります。

10
user3738893

これが純粋なJavaScriptソリューションです。

(function(){

    // Match this timestamp with the release of your code
    var lastVersioning = Date.UTC(2014, 11, 20, 2, 15, 10);

    var lastCacheDateTime = localStorage.getItem('lastCacheDatetime');

    if(lastCacheDateTime){
        if(lastVersioning > lastCacheDateTime){
            var reload = true;
        }
    }

    localStorage.setItem('lastCacheDatetime', Date.now());

    if(reload){
        location.reload(true);
    }

})();

上記はユーザーがあなたのサイトを最後に訪れた時を探します。最後の訪問が新しいコードをリリースする前であった場合は、location.reload(true)を使用してサーバーからページを強制的に更新します。

私は通常これを<head>内の最初のスクリプトとして持っているので、他のコンテンツがロードされる前に評価されます。リロードが発生する必要がある場合、それはユーザーにはほとんど目立ちません。

ローカルストレージを使用してブラウザの最終アクセスタイムスタンプを保存していますが、古いバージョンのIEをサポートする場合は、ミックスにCookieを追加できます。

8
Lloyd Banks

面白い投稿です。ここですべての答えを読んだので、「偽の」クエリ文字列に関する問題はまったく発生したことがないという事実(誰もがこれを使用することに消極的である理由は不明)受け入れられた答えのように)偽のクエリ文字列としてCSSファイルの内容の短いHASHを(ファイルのdatetimeの代わりに)計算することです。

これにより、次のようになります。

<link rel="stylesheet" href="/css/base.css?[hash-here]" type="text/css" />

もちろん、datetimeのソリューションはCSSファイルを編集する場合にもうまくいきますが、それはcssファイルの内容に関するもので、ファイルの日時に関するものではないと思います。

8
Michiel

Laravel(PHP)では、明確でエレガントな方法で(ファイル修正タイムスタンプを使用して)これを実行できます。

<script src="{{ asset('/js/your.js?v='.filemtime('js/your.js')) }}"></script>

CSSでも同様

<link rel="stylesheet" href="{{asset('css/your.css?v='.filemtime('css/your.css'))}}">
8

スクリプトノード(またはcss)要素を動的に作成するクライアントサイドのDOMアプローチが見つかりませんでした。

<script>
    var node = document.createElement("script"); 
    node.type = "text/javascript";
    node.src = 'test.js?'+Math.floor(Math.random()*999999999);
    document.getElementsByTagName("head")[0].appendChild(node);
</script>
6
GreQ

Kipの完璧な解決策に感謝します。

私はそれをZend_view_Helperとして使うように拡張しました。私のクライアントは仮想ホスト上で自分のページを実行しているので、そのためにそれも拡張しました。

それが他の誰かにも役立つことを願っています。

/**
 * Extend filepath with timestamp to force browser to
 * automatically refresh them if they are updated
 *
 * This is based on Kip's version, but now
 * also works on virtual hosts
 * @link http://stackoverflow.com/questions/118884/what-is-an-elegant-way-to-force-browsers-to-reload-cached-css-js-files
 *
 * Usage:
 * - extend your .htaccess file with
 * # Route for My_View_Helper_AutoRefreshRewriter
 * # which extends files with there timestamp so if these
 * # are updated a automatic refresh should occur
 * # RewriteRule ^(.*)\.[^.][\d]+\.(css|js)$ $1.$2 [L]
 * - then use it in your view script like
 * $this->headLink()->appendStylesheet( $this->autoRefreshRewriter($this->cssPath . 'default.css'));
 *
 */
class My_View_Helper_AutoRefreshRewriter extends Zend_View_Helper_Abstract {

    public function autoRefreshRewriter($filePath) {

        if (strpos($filePath, '/') !== 0) {

            // path has no leading '/'
            return $filePath;
        } elseif (file_exists($_SERVER['DOCUMENT_ROOT'] . $filePath)) {

            // file exists under normal path
            // so build path based on this
            $mtime = filemtime($_SERVER['DOCUMENT_ROOT'] . $filePath);
            return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $filePath);
        } else {

            // fetch directory of index.php file (file from all others are included)
            // and get only the directory
            $indexFilePath = dirname(current(get_included_files()));

            // check if file exist relativ to index file
            if (file_exists($indexFilePath . $filePath)) {

                // get timestamp based on this relativ path
                $mtime = filemtime($indexFilePath . $filePath);

                // write generated timestamp to path
                // but use old path not the relativ one
                return preg_replace('{\\.([^./]+)$}', ".$mtime.\$1", $filePath);
            } else {

                return $filePath;
            }
        }
    }

}

歓声とありがとう。

6
lony

次のようにCSS/JS URLを使って乱数を追加するだけです。

example.css?randomNo=Math.random()
5
Ponmudi VN

利用可能なファイルがあるとします。

/styles/screen.css

次のように、URIにバージョン情報を含むクエリパラメータを追加することができます。

/styles/screen.css?v=1234

または、バージョン情報を追加することもできます。

/v/1234/styles/screen.css

私見2番目の方法は、相対URLを使用して画像を参照できるため、CSSファイルに適しています。つまり、background-imageを次のように指定した場合は、次のようになります。

body {
    background-image: url('images/happy.gif');
}

そのURLは事実上以下のようになります。

/v/1234/styles/images/happy.gif

つまり、使用されているバージョン番号を更新すると、サーバーはこれを新しいリソースとして扱い、キャッシュされたバージョンを使用しません。バージョン番号をSubversion/CVS/etcに基づいている場合。これは、CSSファイルで参照されている画像への変更が注目されることを意味します。これは最初の方法では保証されていません。つまり、images/happy.gifに対する相対的なURL /styles/screen.css?v=1235/styles/images/happy.gifであり、バージョン情報は含まれていません。

私はこの手法を使ってJavaサーブレットでキャッシングソリューションを実装し、基礎となるリソースに委譲するサーブレット(つまり/v/*)を使って/styles/screen.cssへのリクエストを処理するだけです。開発モードでは、クライアントにサーバーとのリソースの鮮度を常にチェックするようにキャッシュヘッダーを設定します(TomcatのDefaultServletに委任し、.css.jsなどのファイルが変更されていない場合、通常304になります)。デプロイメントモードでは "cache forever"と言うヘッダを設定しました。

5
Walter Rumsby

Js/cssファイルの誤ったパラメータとしてsession-idを追加すると、 "セッション全体のキャッシュ"を強制することができます。

<link rel="stylesheet" src="myStyles.css?ABCDEF12345sessionID" />
<script language="javascript" src="myCode.js?ABCDEF12345sessionID"></script>

バージョン全体のキャッシュが必要な場合は、ファイルの日付などを印刷するためのコードを追加することができます。 Javaを使用している場合は、カスタムタグを使用してリンクを簡潔に生成できます。

<link rel="stylesheet" src="myStyles.css?20080922_1020" />
<script language="javascript" src="myCode.js?20080922_1120"></script>
5
helios

ASP.NETのために私は高度なオプション(デバッグ/リリースモード、バージョン)を持つ次の解決策を考えます:

そのような方法で含まれているJsまたはCssファイル:

<script type="text/javascript" src="Scripts/exampleScript<%=Global.JsPostfix%>" />
<link rel="stylesheet" type="text/css" href="Css/exampleCss<%=Global.CssPostfix%>" />

Global.JsPostfixとGlobal.CssPostfixは、Global.asaxでは次のように計算されます。

protected void Application_Start(object sender, EventArgs e)
{
    ...
    string jsVersion = ConfigurationManager.AppSettings["JsVersion"];
    bool updateEveryAppStart = Convert.ToBoolean(ConfigurationManager.AppSettings["UpdateJsEveryAppStart"]);
    int buildNumber = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Revision;
    JsPostfix = "";
#if !DEBUG
    JsPostfix += ".min";
#endif      
    JsPostfix += ".js?" + jsVersion + "_" + buildNumber;
    if (updateEveryAppStart)
    {
        Random Rand = new Random();
        JsPosfix += "_" + Rand.Next();
    }
    ...
}
5
Ivan Kochurkin

google chromeには Hard Reload Empty CacheおよびHard Reload のオプションがあります。リロードボタン(Inspectモード)をクリックしたままにすると選択できます。

4
unknown123

私は最近Pythonを使ってこれを解決しました。ここでのコード(他の言語にも簡単に適用できるはずです):

def import_tag(pattern, name, **kw):
    if name[0] == "/":
        name = name[1:]
    # Additional HTML attributes
    attrs = ' '.join(['%s="%s"' % item for item in kw.items()])
    try:
        # Get the files modification time
        mtime = os.stat(os.path.join('/documentroot', name)).st_mtime
        include = "%s?%d" % (name, mtime)
        # this is the same as sprintf(pattern, attrs, include) in other
        # languages
        return pattern % (attrs, include)
    except:
        # In case of error return the include without the added query
        # parameter.
        return pattern % (attrs, name)

def script(name, **kw):
    return import_tag("""<script type="text/javascript" """ +\
        """ %s src="/%s"></script>""", name, **kw)

def stylesheet(name, **kw):
    return import_tag('<link rel="stylesheet" type="text/css" ' +\
        """%s href="/%s">', name, **kw) 

このコードは基本的にファイルのタイムスタンプをクエリパラメータとしてURLに追加します。以下の関数の呼び出し

script("/main.css")

になります

<link rel="stylesheet" type="text/css"  href="/main.css?1221842734">

もちろん利点は、あなたが再びあなたのhtmlを変える必要がないということです、CSSファイルに触れると自動的にキャッシュ無効化を引き起こすでしょう。非常にうまく機能し、オーバーヘッドは目立ちません。

4
pi.

私の開発のために、私はクロムが素晴らしい解決策を持っていると思います。

https://developer.chrome.com/devtools/docs/tips-and-tricks#hard-reload

開発者ツールを開いた状態で、更新ボタンを長押しするだけで、「空のキャッシュとハードリロード」の上にマウスを移動して放します。

これは私の親友です、そして、あなたが欲しいものを手に入れるための超軽量の方法です!

4
Frank Bryce

私はこの答えをSilverStripe http://www.silverstripe.org 特定の答えとして追加していますが、私は探していて見つけたことはありませんでしたが、 http:// apiと答えました。 silverstripe.org/3.0/source-class-SS_Datetime.html#98-110

うまくいけば、これは誰かがSilverStripeテンプレートを使っていて、各ページにキャッシュされた画像を強制的に再ロードしようとするのを助けてくれるでしょう。私の場合、それは一度だけ再生されるgifアニメーションなので、キャッシュされた後は再生されませんでした。私のテンプレートで私は単に追加しました:

?$Now.Format(dmYHis)

ファイルパスの末尾まで移動すると、一意のタイムスタンプが作成され、ブラウザで新しいファイルとして処理されます。

2
pinkp

デッドスレッドを取り戻して申し訳ありません。

@ TomA 正しいです。

"querystring"メソッドを使用しても、 Steve Souders の引用に従ってキャッシュされません。

...一般的なプロキシであるSquidは、クエリ文字列でリソースをキャッシュしません。

@ TomA style.TIMESTAMP.cssを使用することの提案は良いですが、MD5は内容が本当に変更されたときだけ、MD5も同様に変更されます。

2
Tai Li

ここでのすべての答えは、ネーミングスキームのある種のバージョン管理を示唆しているようです。

ブラウザは、Webサーバの応答、特にhttpヘッダを読み取ることによって、何をキャッシュし、何をキャッシュしないかについて十分に認識している必要があります。このリソースは最後に取得してから更新されたものですか? etcetera。

正しく設定されている場合は、アプリケーションのファイルを更新するだけで(ある時点で)ブラウザのキャッシュが更新されるはずです。たとえば、ファイルをキャッシュしないようにブラウザに指示するようにWebサーバーを設定できます(これは悪い考えです)。

それがどのように機能するかについてのより詳細な説明はここにあります https://www.mnot.net/cache_docs/#WORK

2
commonpike

ファイルの内容のMD5ハッシュをそのURLに入れました。そうすれば、非常に長い有効期限を設定でき、ユーザーが古いJSやCSSを持っていることを心配する必要がなくなります。

また、実行時(またはファイルシステムの変更時)にファイルごとに1回計算するので、設計時またはビルドプロセス中に行うことは面白いことではありません。

あなたがASP.NET MVCを使っているなら、あなたはコードをチェックアウトすることができます ここに私の他の答えで

2
Drew Noakes

ファイルの日付を追加するには、サーバー側のコードを使用してください。そうすれば、ファイルが変更されたときにのみキャッシュされて再ロードされます

ASP.NETで

<link rel="stylesheet" href="~/css/[email protected](System.Text.RegularExpressions.Regex.Replace(File.GetLastWriteTime(Server.MapPath("~/css/custom.css")).ToString(),"[^0-9]", ""))" />

<script type="text/javascript" src="~/js/[email protected](System.Text.RegularExpressions.Regex.Replace(File.GetLastWriteTime(Server.MapPath("~/js/custom.js")).ToString(),"[^0-9]", ""))"></script>    

これは次のように単純化できます。

<script src="<%= Page.ResolveClientUrlUnique("~/js/custom.js") %>" type="text/javascript"></script>

Pageを拡張するためにあなたのプロジェクトに拡張メソッドを追加することによって:

public static class Extension_Methods
{
    public static string ResolveClientUrlUnique(this System.Web.UI.Page oPg, string sRelPath)
    {
        string sFilePath = oPg.Server.MapPath(sRelPath);
        string sLastDate = System.IO.File.GetLastWriteTime(sFilePath).ToString();
        string sDateHashed = System.Text.RegularExpressions.Regex.Replace(sLastDate, "[^0-9]", "");

        return oPg.ResolveClientUrl(sRelPath) + "?d=" + sDateHashed;
    }
}
2
Luis Cambustón

以下のプロセスを実行することをお勧めします。

  • screen.1233.css(バージョン管理システムを使用している場合は、番号はSVNのリビジョンになります)

  • 読み込み時間を最適化するためにそれらを縮小する

2
Dan Burzo

Javaサーブレット環境の場合は、 Jawrライブラリ を見ることができます。機能ページでは、キャッシュの処理方法について説明しています。

Jawrは、クライアントにリソースのキャッシュを強制するように最善を尽くします。ファイルが変更されたかどうかをブラウザが尋ねると、304(変更されていない)ヘッダが内容なしで返送されます。一方、Jawrを使用すると、バンドルの新しいバージョンがすべてのクライアントによってダウンロードされることを100%保証できます。リソースへのすべてのURLには、自動的に生成されたコンテンツベースのプレフィックスが含まれます。このプレフィックスは、結果が更新されるたびに自動的に変更されます。新しいバージョンをデプロイすると、バンドルへのURLも変更されるため、クライアントが古いキャッシュバージョンを使用することは不可能になります。

ライブラリはjs/cssの縮小も行いますが、望まない場合はオフにすることができます。

2
holmis83

Git + PHPを使用している場合は、次のコードを使用して、gitリポジトリに変更があるたびにスクリプトをキャッシュから再ロードできます。

exec('git rev-parse --verify HEAD 2> /dev/null', $gitLog);
echo '  <script src="/path/to/script.js"?v='.$gitLog[0].'></script>'.PHP_EOL;
2
readikus

このコードを追加するだけで、ハードリロードを行います(ブラウザにキャッシュされたCSS/JSファイルを強制的にリロードさせます)。 これを.load内で実行し、ループのように更新されないようにします。

 $( window ).load(function() {
   location.reload(true);
});
2
Karan Shaw

最新のブラウザを使用している場合は、マニフェストファイルを使用して、更新する必要があるファイルをブラウザに通知できます。これは、ヘッダ、URLのバージョンなどを必要としません。

詳細については、以下を参照してください。 https://developer.mozilla.org/nl/docs/Web/HTML/Applicatie_cache_gebruiken#Introduction

2
Jos

私はリソースURLにタイムスタンプベースまたはハッシュベースの微分器を使用するアプローチに問題があると思います。例えばへのリンクを含むページ。スタイルシート も同様にキャッシュされる可能性があります 。そのため、キャッシュされたページは古いバージョンのスタイルシートを要求する可能性がありますが、要求されたページでは動作する可能性があるまたは動作しない可能性がある最新バージョンが提供されます。

これを修正するには、リクエストしているページをno-cacheヘッダーまたはメタで保護して、すべてのロードで確実に更新されるようにする必要があります。または、リクエストしたページがスタイルファイルのバージョンを取得できるように、サーバーにデプロイしたスタイルファイルの すべてのバージョン をそれぞれ個別のファイルとして、それらを区別せずに維持する必要がありますのために設計されました。後者の場合、基本的にHTMLページとスタイルシートのバージョンを結び付けます。これは静的に行うことができ、サーバーロジックを必要としません。

1
ThomasH

"SCdFによって提案されたもう一つのアイデアは、偽のクエリ文字列をファイルに追加することです。(タイムスタンプを自動的に偽のクエリ文字列として使用するPythonコードがpiから提出されました。)ブラウザがファイルをクエリ文字列でキャッシュするわけではありません(ブラウザにファイルをキャッシュさせ、将来の訪問時にそれを使用させることを忘れないでください。偽のクエリ文字列で何が起こるか、私はその答えを受け入れていません。」

<link rel = "スタイルシート" href = "file.css?<?= hash_hmac( 'sha1'、session_id()、md5_file(" file.css "));?>" />

ファイルをハッシュすると、ファイルが変更されたときにクエリ文字列も変更されます。そうでなければ、それは変わりません。セッションごとにリロードも強制されます。

必要に応じて、書き換えを使ってブラウザに新しいURIだと思わせることもできます。

1

Script.jsのキャッシュを無効にする ローカル開発の場合のみ pure JSでは

ランダムにscript.jsを挿入しますか?wizardry = 1231234そして通常のscript.jsをブロックします

<script type="text/javascript">
  if(document.location.href.indexOf('localhost') !== -1) {
    const scr = document.createElement('script');
    document.setAttribute('type', 'text/javascript');
    document.setAttribute('src', 'scripts.js' + '?wizardry=' + Math.random());
    document.head.appendChild(scr);
    document.write('<script type="application/x-suppress">'); // prevent next script(from other SO answer)
  }
</script>
<script type="text/javascript" src="scripts.js">
1
Pawel

ASP.Net Webサイトに対する別の提案

  1. 静的ファイルごとに異なるcache-control:max-age値を設定します。
  2. Css/jsファイルの場合、サーバー上でこれらのファイルを変更する可能性が高いので、最小のcache-control:1または2分のmax-age値、または必要に応じたものを設定してください。
  3. 画像の場合は、遠い日付をcache-control:max-ageの値として設定します(360日など)。
  4. そうすることによって、最初のリクエストをしたときに、すべての静的コンテンツは200-OKレスポンスでクライアントマシンにダウンロードされます。
  5. その後のリクエストと2分後に、cssファイルとjsファイルに対する304-Not Modifiedリクエストが表示され、css/jsのバージョン管理を回避できます。
  6. キャッシュが期限切れになるまでキャッシュされたメモリから使用されるため、イメージファイルは要求されません。
  7. 以下のweb.config設定を使用することで、上記の動作を実現できます。

必要なファイルをすべてリストした単一のindex.htmlしかない、SPA用のソリューションを探すときに、私はこの問題に遭遇しました。私は私を助けたいくつかのリードを得ましたが、私は迅速で簡単な解決策を見つけることができませんでした。

最後に、私は出版プロセスの一環としてhtml/js index.htmlを自動バージョン化するのに必要なクイックページ(すべてのコードを含む)を書きました。それは完全に動作し、最後に変更された日付に基づいて新しいファイルを更新するだけです。

私の投稿は http://blueskycont.com/wp/2016/05/12/autoversion-your-spa-index-html/ で見ることができます。そこにはフリーワーキングもあります。

コードの内容は

       private void ParseIndex(string inFile, string addPath, string outFile)
    {
        string path = Path.GetDirectoryName(inFile);
        HtmlAgilityPack.HtmlDocument document = new HtmlAgilityPack.HtmlDocument();
        document.Load(inFile);
        foreach (HtmlNode link in document.DocumentNode.Descendants("script"))
        {
            if (link.Attributes["src"]!=null)
            {
                resetQueryString(path, addPath, link, "src");
            }
        }
        foreach (HtmlNode link in document.DocumentNode.Descendants("link"))
        {
            if (link.Attributes["href"] != null && link.Attributes["type"] != null)
            {
                if (link.Attributes["type"].Value == "text/css" || link.Attributes["type"].Value == "text/html")
                {
                    resetQueryString(path, addPath, link, "href");
                }
            }
        }
        document.Save(outFile);
        MessageBox.Show("Your file has been processed.", "Autoversion complete");
    }

    private void resetQueryString(string path, string addPath, HtmlNode link, string attrType)
    {
        string currFileName = link.Attributes[attrType].Value;

        string uripath = currFileName;
        if (currFileName.Contains('?')) uripath = currFileName.Substring(0, currFileName.IndexOf('?'));
        string baseFile = Path.Combine(path, uripath);
        if (!File.Exists(baseFile)) baseFile = Path.Combine(addPath, uripath);
        if (!File.Exists(baseFile)) return;
        DateTime lastModified = System.IO.File.GetLastWriteTime(baseFile);
        link.Attributes[attrType].Value = uripath + "?v=" + lastModified.ToString("yyyyMMddhhmm");
    }
1
statler

ここでの多くの回答は、URLにタイムスタンプを追加することを提唱しています。プロダクションファイルを直接変更しているのでなければ、ファイルのタイムスタンプはファイルが変更された時刻を反映する可能性は低いです。ほとんどの場合、これによりファイル自体よりもURLが頻繁に変更されます。これが、levikや他の人が示唆しているようにMD5などのファイルの内容の高速ハッシュを使用する必要がある理由です。

値は、ファイルが要求されるたびにではなく、構築時または実行時に1回計算する必要があることに注意してください。

例として、stdinからファイル名のリストを読み取り、ハッシュを含むjsonファイルをstdoutに書き込む単純なbashスクリプトがあります。

#!/bin/bash
# create a json map from filenames to md5s
# run as hashes.sh < inputfile.list > outputfile.json

echo "{"
delim=""
while read l; do
    echo "$delim\"$l\": \"`md5 -q $l`\""
    delim=","
done
echo "}"

このファイルは、サーバーの起動時にロードされ、ファイルシステムを読み取る代わりに参照される可能性があります。

1
undefined

キャッシュを回避しようとしている開発者の場合、chromeネットワークタブにはキャッシュオプションが無効になっています。それ以外の場合は、2つのスクリプトタグを使用して、サーバーレンダリングフレームワークなしで実行できます。

<script type="text/javascript">
    document.write('<script type="text/javascript" src="myfile.js?q=' + Date.now() + '">
    // can't use myfile.js stuff yet
</script>')
<script type="text/javascript">
    // do something with myfile.js
</script>
0
astronought

私が知っている最善かつ迅速な方法の1つは、CSSまたはJSファイルがあるフォルダーの名前を変更することです。開発者向けのOR。 CSS/jsファイルの名前をバージョンのように変更します。

<link rel="stylesheet" href="cssfolder/somecssfile-ver-1.css"/>

Jsファイルについても同じことをしてください。

0
Bangash

これを行う私の方法は、単純にlink要素をサーバー側に含めることです。

<!--#include virtual="/includes/css-element.txt"-->

css-element.txtの内容は次のとおりです。

<link rel="stylesheet" href="mycss.css"/>

つまり、my-new-css.cssにリンクしたい日など、インクルードを変​​更するだけです。

0
AmbroseChapel

既存の回答から少し改善しています...

乱数またはセッションIDを使用すると、リクエストごとにリロードが発生します。理想的には、何らかのjs/cssファイルでコードの変更が行われた場合にのみ変更する必要があるかもしれません。共通JSPファイルを他の多くのjspおよびjsファイルのテンプレートとして使用する場合共通JSPファイルに以下を追加

<%@ taglib prefix="c" uri="http://Java.Sun.com/jsp/jstl/core"%>
<c:set var = "version" scope = "application" value = "1.0.0" />

Jsファイルのインクルードで以下のようにすべての場所で上記の変数を使用してください。

<script src='<spring:url value="/js/myChangedFile.js?version=${version}"/>'></script>

利点:

1)この方法は、1か所だけでバージョン番号を変更するのに役立ちます。

2)適切なバージョン番号(通常はビルド/リリース番号)を維持すると、コードの変更が正しくデプロイされていることを確認または確認するのに役立ちます(ブラウザの開発者コンソールから)。

もう1つの役に立つヒント:

クロムブラウザを使用している場合は、開発ツールが開いているときにキャッシュを無効にすることができます。 ChromeでF12キーを押しながらF1キーを押して、設定>設定>ネットワーク>キャッシュを無効にします(DevToolsが開いている間)。

Chrome DevTools

0

まあ、私はそれが次のようにJSファイルのバージョンに乱数を追加することにより、各時間のjsに、ページの読み込みをバージョンを変更することで、私のように動作してきました。

// Add it to the top of the page
<?php
srand();
$random_number = Rand();
?>

そして、次のようにjsのバージョンに乱数を適用します。

<script src="file.js?version=<?php echo $random_number;?>"></script>
0
Al3abMizo Games