クライアントにJavaScriptファイルの更新を強制するにはどうすればよいですか?


595

現在、プライベートベータ版で作業しており、かなり急速な変更を行っている段階です。ただし、使用量が増加し始めているため、このプロセスの速度は遅くなります。そうは言っても、私たちが遭遇している1つの問題は、新しいJavaScriptファイルで更新をプッシュした後でも、クライアントのブラウザーがファイルのキャッシュバージョンを使用し、更新が表示されないことです。明らかに、サポートコールではctrlF5、サーバーに最新のファイルを確実に取得するために更新するように通知するだけですが、その前に処理することをお勧めします。

私たちの現在の考えは、JavaScriptファイルの名前にバージョン番号を添付し、変更が加えられたときに、スクリプトのバージョンをインクリメントしてすべての参照を更新することです。これで間違いなく仕事は終わりますが、リリースごとにリファレンスを更新するのは面倒です。

私たちがこれに対処する最初のものではないと確信しているので、私はそれをコミュニティに捨てるだろうと考えました。コードを更新するときに、クライアントがキャッシュを確実に更新するようにするにはどうすればよいですか?上記の方法を使用している場合、変更を簡素化するプロセスを使用していますか?


回答:


529

私の知る限り、一般的な解決策は?<version>、スクリプトのsrcリンクにを追加することです。

例えば:

<script type="text/javascript" src="myfile.js?1500"></script>

この時点で、すべてのスクリプトタグでこれらの「バージョン番号」をインクリメントするには、find-replaceよりも良い方法はないと思いますか?

あなたはバージョン管理システムにあなたのためにそれをさせるかもしれませんか?ほとんどのバージョン管理システムには、たとえばチェックイン時にリビジョン番号を自動的に挿入する方法があります。

次のようになります。

<script type="text/javascript" src="myfile.js?$$REVISION$$"></script>

もちろん、このようなより良い解決策は常にあります。


5
IE7がこれを無視するかどうか知っていますか?IE8の互換性ビューでテストすると、追加されたデータを無視し、キャッシュされたファイルを使用しているようです。
シェーンリスル、2011年

4
私は常にクエリ文字列が?ver = 123のようなキーと値のペアであることを知っていました。ありがとう!:)
Ankur-m

6
バージョン番号の高低ではなく、追加された変数の値を、ブラウザーがまだキャッシュできなかったものに変更することだと思います。
Max Girkens 2013

2
私たちは最近同じ問題に遭遇し、私が思いつくことができた最高のものは、「?mod = 123456」を付けた単純な関数でした。ここで、123456は、ファイルの変更された日付のUNIXタイムスタンプです。それは問題を修正するように思われますが、適切な場所でキャッシュを可能にします。ただし、ブラウザがこのディレクティブを無視して古いJSを使用しているのを見たままですが、エレガントな「完全な修正」があることはわかりません。
VPel

31
認識のために:これはハックと見なされます。このメソッドはブラウザをだまして、新しいファイルが指定されていると思い込ませます。それは単にそれを解釈することなく完全なファイル名を見るからです。はとfoo.js?1同じ名前ではないfoo.js?2ため、ブラウザはそれらを2つの異なるファイルと見なします。1つの欠点は、両方のファイルが同時にユーザーのキャッシュに存在し、不要なスペースを占有することです。
リーホワイト

88

URLに現在の時刻を追加することは、確かに一般的な解決策です。ただし、必要に応じて、これをWebサーバーレベルで管理することもできます。サーバーは、JavaScriptファイルのさまざまなHTTPヘッダーを送信するように構成できます。

たとえば、ファイルを強制的に1日以内にキャッシュするには、次のように送信します。

Cache-Control: max-age=86400, must-revalidate

ベータ版の場合、ユーザーに常に最新の状態を取得させるには、次のようにします。

Cache-Control: no-cache, must-revalidate

3
もっと具体的に教えてもらえますか?
Kreker

6
彼は、ファイルごとにWebサーバーから送信されたヘッダーについて話しています。たとえば、Apacheで構成可能である必要があります。これが最良のアプローチになると思います
ピエール・ド・レスピーヌ

1
これはどこで設定しますか?
ディエゴ

2
開発用ウェブアプリの場合、これはおそらく良いソリューションです。キャッシュを永久に無効にしたくない本番サイトでは、すべてのターゲットクライアントブラウザーがサイトにアクセスしたことを知らない限り、これは良い解決策ではありません。Webサーバーの潜在的な機能について考えさせられます。構成された展開日に従ってmax-ageパラメーターを調整します。それは素晴らしいでしょう。
Claude Brisson 2017年

Chromeでは、適切にキャッシュするためにこれらの設定が必要です。それらがなければ、Chromeはファイルを永久にキャッシュします。Mozillaはより合理的なデフォルトを使用しています。詳しくは、agiletribe.wordpress.com
2018/01/29

42

Google Page-Speed:静的リソースのURLにクエリ文字列を含めないでください。ほとんどのプロキシ、特にバージョン3.0までのSquidは、「?」でリソースをキャッシュしません。Cache-control:publicヘッダーが応答に存在する場合でも、URLに含まれます。これらのリソースのプロキシキャッシュを有効にするには、静的リソースへの参照からクエリ文字列を削除し、代わりにパラメーターをファイル名自体にエンコードします。

この場合、バージョンをURL ex:http : //abc.com/ v1.2 /script.jsに含め、apache mod_rewriteを使用してリンクをhttp://abc.com/script.jsにリダイレクトできます。バージョンを変更すると、クライアントブラウザが新しいファイルを更新します。


私は試しましたか?ソリューションとIE8で、JavaScriptエラーが発生します。Mod rewriteはオプションですが、ほとんどの場合、サーバーをそれほど制御することはできません。私は、JSファイル自体にバージョンを追加するか、バージョンごとにフォルダを持つ好むだろう
カルティクSankarの

@HắcHuyềnMinh:ただし、スクリプトを再ロードする場合、プロキシキャッシュから再ロードしないでください...
Stefan Steiger

34

この使用法は廃止されました:https ://developer.mozilla.org/en-US/docs/Web/HTML/Using_the_application_cache

この回答は6年遅れですが、多くの場所でこの回答は見当たりません... HTML5は、この問題を解決するために使用されるアプリケーションキャッシュを導入しました。私が書いている新しいサーバーコードが人々のブラウザーに保存されている古いJavaScriptをクラッシュさせているのを発見したので、JavaScriptを期限切れにする方法を見つけたかったのです。次のようなマニフェストファイルを使用します。

CACHE MANIFEST
# Aug 14, 2014
/mycode.js

NETWORK:
*

ユーザーがキャッシュを更新するたびに、新しいタイムスタンプでこのファイルを生成します。補足として、これを追加した場合、マニフェストが指示するまで、ブラウザーは(ユーザーがページを更新した場合でも)リロードしません


マニフェストファイルを更新するのを覚えている限り、このソリューションは本当に優れています:)
Mattis

24
この機能は、Web標準から削除されているとしてドキュメントをお読みくださいdeveloper.mozilla.org/en-US/docs/Web/HTML/...
フラビアObreja

1
FWIW、私はこのソリューションを使用しなくなりました。この?<version> アプローチを使用/維持する方がはるかに簡単でした。
amos

28

ロードサイズとしてファイルサイズを追加するのはどうですか?

<script type='text/javascript' src='path/to/file/mylibrary.js?filever=<?=filesize('path/to/file/mylibrary.js')?>'></script>

したがって、ファイルを更新するたびに、「filever」パラメーターが変更されます。

ファイルを更新し、更新の結果が同じファイルサイズになる場合はどうですか?オッズは何ですか?


4
これはPHPタグを使用しており、PHPを使用している場合、それは確かに良い考えです。
Jerther 2017

1
変更点を追加する方がファイルサイズよりも良いと思います:)
Mazz

2
私の最初の考えは、バージョンの代わりにファイルのハッシュを追加することです。
Mike Cheel、2017

タイムスタンプをUnixに追加しても機能すると思いますよね?例: '... file.js?filever = <?= time()?>
ガランダ

3
filemtime($ file)を使用すると、ファイルのタイムスタンプが出力されます。time()を使用すると、秒ごとに変化するため、キャッシュを使用できません。
neoteknic 2017年

19

すべてのブラウザが「?」を含むファイルをキャッシュするわけではありません 初期化。可能な限りキャッシュされるようにするため、ファイル名にバージョンを含めました。

の代わりにstuff.js?123、私はしましたstuff_123.js

私は行くmod_redirectためにApacheで(私は思う)使用しましhave stuff_*.jsstuff.js


mod_redirectを使用して.htaccessで行ったことについて詳しく教えてください。
Venkat D.

3
この方法の詳細な説明は、particletree.com
Karl Bartel

3
.htaccess後で参照できるように、回答にコードを含めることができればすばらしいと思います。
Fizzix、2016

1
「?」が付いているファイルをキャッシュしないブラウザー 初期化?
rosell.dk

13

ASP.NETページの場合、次を使用しています

<script src="/Scripts/pages/common.js" type="text/javascript"></script>

AFTER(強制リロード)

<script src="/Scripts/pages/common.js?ver<%=DateTime.Now.Ticks.ToString()%>" type="text/javascript"></script>

DateTime.Now.Ticksの追加は非常にうまく機能します。


31
これは、クライアント側のすべてのキャッシュメカニズムに反します。ダミーパラメータは、リリースごとにユニークだろう「{メジャーバージョン} _ {minor_version} _ {ビルド番号} _ {リビジョン}のようなものに置き換える必要があります。
Tohid

14
これはおそらく開発環境での神の解決策ですが、本番環境には適していません。これにより、ページがファイルに読み込まれるたびに、キャッシュが完全に無効になります。1つの50Kbファイルで1日あたり10kのページロードを想像してください。これは、毎日500MbのJavascriptファイルを表します。
PhilDulac 2016

@PhilDulacこれをTicksから変更して、たとえば、日の文字列値、月、または月の週を返すことができます。最終的には、vアプローチの使用方法を示すだけです
アレックス

3
@alex確かに。答えで示されている使用法が本番環境に移行すると、開発には現れない影響が生じる可能性があることを警告したいと思います。
PhilDulac 2016年

2
新しいコピーが毎日1回読み込まれるようにするための可能な方法は、 '<script src = "/ Scripts / pages / common.js?ver <%= DateTime.Now.ToString(" yyyyMMdd ")%>"タイプを使用することです。 = "text / javascript"> </ script> '。つまり、1日の初めに1回ロードされてから、キャッシュされます。
Robb Sadler

7

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();
    }
    ...
}

私は.Ticksを使用しています(このページの私の回答を参照してください)
Ravi Ram

5

最近の一般的な方法は、ファイル名の一部としてコンテンツハッシュコードを生成し、ブラウザ、特にIEにJavaScriptファイルまたはCSSファイルをリロードさせることです。

例えば、

ベンダー。a7561fb0e9a071baadb9 .js
main。b746e3eb72875af2caa9 .js

これは通常、webpackなどのビルドツールの仕事です。ここではもっとあるの詳細を誰もがあなたがWebPACKのを使用している場合は試してみたい場合。


4

JSファイルにリンクするページを生成している場合、簡単な解決策は、ファイルの最終変更タイムスタンプを生成されたリンクに追加することです。

これはHuppieの回答と非常に似ていますが、キーワード置換なしのバージョン管理システムで機能します。また、現在の時刻を追加するよりも優れています。ファイルをまったく変更していなくても、キャッシュされないためです。


メンテナンスが最も簡単なので、このソリューションが気に入っています。.jsファイルを更新する場合は、これで完了です。コードは最後に更新されたタイムスタンプを自動的に追加するため、ファイルへの参照も更新する必要はありません。
NL3294 2016年

3

jQuery関数getScriptを使用して、ページが読み込まれるたびにjsファイルが確実に読み込まれるようにすることもできます。

これは私がそれをした方法です:

$(document).ready(function(){
    $.getScript("../data/playlist.js", function(data, textStatus, jqxhr){
         startProgram();
    });
});

http://api.jquery.com/jQuery.getScript/で関数を確認してください

デフォルトでは、$。getScript()はキャッシュ設定をfalseに設定します。これにより、タイムスタンプ付きのクエリパラメータがリクエストURLに追加され、ブラウザがリクエストされるたびにスクリプトがダウンロードされるようになります。


8
変更が発生しない場合は、ファイルをキャッシュする必要があります。
レオリー

3

ではPHP

function latest_version($file_name){
    echo $file_name."?".filemtime($_SERVER['DOCUMENT_ROOT'] .$file_name);
}

ではHTML

<script type="text/javascript" src="<?php latest_version('/a-o/javascript/almanacka.js'); ?>">< /script>

使い方:

HTMLで、filepath名前と同じように記述しますが、関数のみです。PHPはfiletimeファイルのを取得し、filepath+name+"?"+time最新の変更のを返します


3

私たちはユーザー向けのSaaSを作成し、Webサイトのページに添付するスクリプトを提供していますが、ユーザーが機能用にスクリプトをWebサイトに添付するため、スクリプトを使用してバージョンを添付することはできず、強制することはできません。スクリプトを更新するたびにバージョンを変更するには

そこで、ユーザーが元のスクリプトを呼び出すたびに新しいバージョンのスクリプトをロードする方法を見つけました

ユーザーに提供されるスクリプトリンク

<script src="https://thesaasdomain.com/somejsfile.js" data-ut="user_token"></script>

スクリプトファイル

if($('script[src^="https://thesaasdomain.com/somejsfile.js?"]').length !== 0) {
   init();
} else {
   loadScript("https://thesaasdomain.com/somejsfile.js?" + guid());
}

var loadscript = function(scriptURL) {
   var head = document.getElementsByTagName('head')[0];
   var script = document.createElement('script');
   script.type = 'text/javascript';
   script.src = scriptURL;
   head.appendChild(script);
}

var guid = function() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

var init = function() {
    // our main code
}

説明:

ユーザーがウェブサイトで提供されたスクリプトを添付し、jQueryセレクターを使用して、スクリプトが添付されている一意のトークンが存在するかどうかを確認し、存在しない場合は新しいトークン(またはバージョン)で動的にロードします

これは同じスクリプトを2回呼び出すため、パフォーマンスの問題となる可能性がありますが、ユーザーまたはクライアントに与えられた実際のスクリプトリンクにバージョンを入れずに、スクリプトがキャッシュから読み込まれないようにするという問題を本当に解決します

免責事項:あなたのケースでパフォーマンスが大きな問題である場合は使用しないでください。


2

asp.net mvc では、jsファイルのバージョン番号に@ DateTime.UtcNow.ToString()を使用できます。バージョン番号は日付に応じて自動的に変更され、クライアントのブラウザーでjsファイルが自動的に更新されるように強制します。私はこの方法を使用していますが、これはうまくいきます。

<script src="~/JsFilePath/JsFile.js?v=@DateTime.UtcNow.ToString()"></script>

他の提案されたソリューションと同様に、これによりファイルがキャッシュされることはありません。これは通常は望ましくありません。ファイルに変更が加えられていない限り、クライアントは毎回変更されていないファイルを再度ダウンロードするのではなく、キャッシュされたバージョンを使用する必要があります。
フィリップストラットフォード

あなたの理由で以下のコードを使用できます。バージョン番号が<script src = "~/JsFilePath/JsFile.js?v=@GetAppVersionNumber()"> </ script>のキャッシュファイル
ドラゴン

2

location.reload(true);

https://www.w3schools.com/jsref/met_loc_reload.aspを参照してください

このコード行を動的に呼び出して、この問題を回避するために、ブラウザーのキャッシュからではなく、WebサーバーからJavaScriptが確実に再取得されるようにします。


onload="location.reload();"フォームにを追加すると、ページを再起動する代わりに、更新後に新しいJSを取得できます。これははるかにエレガントなソリューションです。ありがとう!
ZX9

おかげで、IPが認識されているかどうかのチェックでこれを使用できましたが、最後の更新以降、ログインに使用されていないため、ユーザーが最初にログインした後、インデックスページでこれを実行しました。
Fi Horan

onload = "location.reload(true);" 上記は私には機能しませんでした(フラスコと現在のバージョンのChromeを使用): w3schools.com/jsref/met_loc_reload.asp
aspiringGuru

1

1つの解決策は、リソースをフェッチするときに、タイムスタンプを含むクエリ文字列をURLに追加することです。これは、ブラウザがクエリ文字列を含むURLからフェッチされたリソースをキャッシュしないという事実を利用しています。

ただし、ブラウザがこれらのリソースをまったくキャッシュしないようにしたくないでしょう。それらをキャッシュしたい可能性が高いですが、ファイルが使用可能になったときにブラウザーにファイルの新しいバージョンをフェッチさせたいと考えています。

最も一般的な解決策は、ファイル名自体にタイムスタンプまたはリビジョン番号を埋め込むことです。これは、コードを修正して正しいファイルを要求する必要があるため、もう少し作業が必要ですが、たとえば、バージョン7 snazzy_javascript_file.js(つまりsnazzy_javascript_file_7.js)は、バージョン8をリリースするまでブラウザーにキャッシュされ、コードは次のように変更されます。snazzy_javascript_file_8.js代わりにフェッチします。


1

使用することの利点file.js?V=1を超えるAをfileV1.js、サーバー上のJavaScriptファイルの複数のバージョンを保存する必要がないということです。

私が直面する問題file.js?V=1は、新しいバージョンのライブラリユーティリティを使用すると、別のJavaScriptファイルに依存するコードが壊れる可能性があることです。

下位互換性のjQuery.1.3.jsためjQuery.1.1.jsに、必要に応じて古いページをアップグレードする準備ができるまで、新しいページに使用し、既存のページを使用できるようにする方がはるかに良いと思います。


1

GETブラウザのキャッシュを防ぐには、バージョン変数を使用します。

?v=AUTO_INCREMENT_VERSIONURLの末尾に追加すると、ブラウザのキャッシュが防止され、キャッシュされたスクリプトのすべてが回避されます。


1

私の同僚は、http: //www.stefanhayden.com/blog/2006/04/03/css-caching-hack/に(cssに関して)投稿した直後に、そのメソッドへの参照を見つけました。他の人がそれを使用していて、動作しているように見えるのは良いことです。この時点で、すべてのスクリプトタグでこれらの「バージョン番号」をインクリメントするには、find-replaceよりも良い方法はないと思いますか?



1

タグヘルパーを介したASP.NET Coreのキャッシュバスティングはこれを処理し、ファイルが変更されるまでブラウザーがキャッシュされたスクリプト/ cssを保持できるようにします。タグヘルパーasp-append-version = "true"をスクリプト(js)またはリンク(css)タグに追加するだけです。

<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true"/>

Dave Paquetteが、キャッシュの無効化の良い例と説明をここに示しています(ページの下部)キャッシュの無効化


これは通常のASP.NETでは機能しませんか?スクリプトタグにasp-append-versionを追加してみましたが、ブラウザに表示されるのは、asp-append-version属性を含め、ソースに表示されているとおりのスクリプトタグだけです。
tolsen64 2017

これは、タグヘルパーに関連付けられた.NET Core属性です。スクリプト名にバージョンを追加して、サーバー/ブラウザが常に最新バージョンとダウンロードを確認できるようにします
ccherwin

0

最も簡単な解決策は?ブラウザにまったくキャッシュさせないでください。現在の時刻(ミリ秒単位)をクエリとして追加します。

(まだベータ版ですので、パフォーマンスを最適化しないことを正当な理由とすることができます。ただし、ここではYMMVです。)


13
私見これは貧弱な解決策です。ベータ版ではなく、重要な更新をプッシュした場合はどうなりますか?
d -_- b

0

1つの簡単な方法。htaccessを編集

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} \.(jpe?g|bmp|png|gif|css|js|mp3|ogg)$ [NC]
RewriteCond %{QUERY_STRING} !^(.+?&v33|)v=33[^&]*(?:&(.*)|)$ [NC]
RewriteRule ^ %{REQUEST_URI}?v=33 [R=301,L]

これにより、パフォーマンスの点で次善のリダイレクトですが、有効なソリューションです。
twicejr

0

以下は私のために働きました:

<head>
<meta charset="UTF-8">
<meta http-equiv="cache-control" content="no-cache, must-revalidate, post-check=0, pre-check=0" />
<meta http-equiv="cache-control" content="max-age=0" />
<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" />
</head>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.