クライアントに JavaScript ファイルを強制的に更新するにはどうすればよいですか?
-
09-06-2019 - |
質問
私たちは現在プライベート ベータ版で作業しているため、かなり急速な変更を加えている最中ですが、明らかに使用量が増加し始めているため、このプロセスは遅くなる予定です。そうは言っても、私たちが直面している問題の 1 つは、新しい JavaScript ファイルを使用して更新をプッシュした後、クライアントのブラウザーが引き続きファイルのキャッシュされたバージョンを使用し、更新が表示されないことです。明らかに、サポート電話では、次のことを行うように伝えるだけで済みます。 CtrlF5 サーバーから最新のファイルを確実に取得するために更新しますが、その前にこれを処理することが望ましいでしょう。
私たちの現在の考えは、単純に JavaScript ファイルの名前にバージョン番号を付加し、変更が行われたときにスクリプトのバージョンをインクリメントしてすべての参照を更新することです。これで間違いなく仕事は完了しますが、リリースごとに参照を更新するのは面倒になる可能性があります。
私たちがこの問題に最初に対処したわけではないと確信しているため、コミュニティにこの問題を投げかけようと思いました。コードを更新するときにクライアントがキャッシュを更新するようにするにはどうすればよいでしょうか?上記の方法を使用している場合、変更を簡素化するプロセスを使用していますか?
解決
私の知る限り、一般的な解決策は ?<version>
スクリプトの src リンクに移動します。
例えば:
<script type="text/javascript" src="myfile.js?1500"></script>
現時点では、すべてのスクリプト タグの「バージョン番号」を増やすには、検索と置換よりも良い方法はないのではないかと思います。
バージョン管理システムにそれをやってもらうこともできるでしょうか?ほとんどのバージョン管理システムには、たとえばチェックイン時にリビジョン番号を自動的に挿入する方法があります。
次のようになります。
<script type="text/javascript" src="myfile.js?$$REVISION$$"></script>
もちろん、次のようなより良い解決策は常にあります。 これです.
他のヒント
URL に現在時刻を追加するのは、確かに一般的な解決策です。ただし、必要に応じて、これを Web サーバー レベルで管理することもできます。サーバーは、JavaScript ファイルに異なる HTTP ヘッダーを送信するように構成できます。
たとえば、ファイルが 1 日以内にキャッシュされるようにするには、次のように送信します。
Cache-Control: max-age=86400, must-revalidate
ベータ版の場合、ユーザーが常に最新のものを取得できるようにしたい場合は、次のようにします。
Cache-Control: no-cache, must-revalidate
Googleのページ速度:静的リソースの URL にはクエリ文字列を含めないでください。ほとんどのプロキシ、特にバージョン 3.0 までの Squid は、Cache-control が次の場合でも、URL に "?" を含むリソースをキャッシュしません。パブリックヘッダーが応答に存在します。これらのリソースのプロキシ キャッシュを有効にするには、静的リソースへの参照からクエリ文字列を削除し、代わりにパラメータをファイル名自体にエンコードします。
この場合、URL にバージョンを含めることができます。例: http://abc.com/v1.2/script.js にアクセスし、Apache mod_rewrite を使用してリンクをリダイレクトします。 http://abc.com/script.js. 。バージョンを変更すると、クライアント ブラウザによって新しいファイルが更新されます。
この使用法は廃止されました。 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:
*
ユーザーがキャッシュを更新するたびに、新しいタイムスタンプを持つこのファイルを生成します。補足として、これを追加すると、ブラウザは ない マニフェストで指示されるまで (ユーザーがページを更新した場合でも) リロードします。
ファイルサイズをロードパラメータとして追加してみてはいかがでしょうか?
<script type='text/javascript' src='path/to/file/mylibrary.js?filever=<?=filesize('path/to/file/mylibrary.js')?>'></script>
したがって、ファイルを更新するたびに、「fileever」パラメータが変更されます。
ファイルを更新したときに、更新結果のファイル サイズが同じになった場合はどうでしょうか。確率は何ですか?
すべてのブラウザがファイルをキャッシュするわけではありません '?' 初期化。可能な限りキャッシュされるようにするために、ファイル名にバージョンを含めました。
だから代わりに stuff.js?123
, 、 やった stuff_123.js
私が使用した mod_redirect
(私は)Apacheでtoに have stuff_*.js
持ち帰り stuff.js
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 を追加すると、非常にうまく機能します。
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();
}
...
}
JS ファイルにリンクするページを生成している場合、簡単な解決策は、生成されたリンクにファイルの最終変更タイムスタンプを追加することです。
これはHuppieの答えと非常に似ていますが、キーワード置換なしのバージョン管理システムで機能します。また、ファイルがまったく変更されていない場合でもキャッシュを防止できるため、現在時刻を追加するよりも優れています。
私たちはユーザー向けに 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
}
説明:
ユーザーは、Web サイトに提供されたスクリプトを添付しました。jQuery セレクターを使用して、スクリプトに添付された一意のトークンが存在するかどうかを確認し、存在しない場合は、新しいトークン (またはバージョン) で動的にロードします。
これは、同じスクリプトを 2 回呼び出すことになり、パフォーマンスの問題になる可能性がありますが、ユーザーまたはクライアントに与えられる実際のスクリプト リンクにバージョンを含めずに、スクリプトがキャッシュから読み込まれないようにするという問題は実際に解決されます。
免責事項:パフォーマンスが大きな問題となる場合は使用しないでください。
jQuery 関数 getScript を使用すると、ページが読み込まれるたびに js ファイルが実際に読み込まれることを確認することもできます。
これが私がやった方法です:
$(document).ready(function(){
$.getScript("../data/playlist.js", function(data, textStatus, jqxhr){
startProgram();
});
});
で機能を確認してください http://api.jquery.com/jQuery.getScript/
デフォルトでは、$.getScript() はキャッシュ設定を false に設定します。これにより、タイムスタンプ付きのクエリ パラメータがリクエスト URL に追加され、リクエストされるたびにブラウザがスクリプトをダウンロードするようになります。
解決策の 1 つは、リソースを取得するときに、タイムスタンプを含むクエリ文字列を URL に追加することです。これは、ブラウザーがクエリ文字列を含む URL から取得したリソースをキャッシュしないという事実を利用しています。
ただし、ブラウザーがこれらのリソースをまったくキャッシュしないことは望ましくないでしょう。ファイルをキャッシュしておきたいが、ファイルの新しいバージョンが利用可能になったときにブラウザがそれを取得するようにしたい場合の方が多いでしょう。
最も一般的な解決策は、ファイル名自体にタイムスタンプまたはリビジョン番号を埋め込むことのようです。正しいファイルをリクエストするにはコードを変更する必要があるため、これには少し手間がかかりますが、これはつまり、次のことを意味します。バージョン 7 snazzy_javascript_file.js
(すなわち、 snazzy_javascript_file_7.js
) はバージョン 8 がリリースされるまでブラウザ上にキャッシュされ、リリースされるとコードが変更されて取得されます。 snazzy_javascript_file_8.js
その代わり。
バージョンを使用する GET
ブラウザのキャッシュを防ぐための変数。
追加中 ?v=AUTO_INCREMENT_VERSION
URL の最後に追加すると、ブラウザーのキャッシュが防止され、キャッシュされたすべてのスクリプトが回避されます。
私が (CSS を参照して) 投稿した直後に、同僚がそのメソッドへの参照を見つけました。 http://www.stefanhayden.com/blog/2006/04/03/css-caching-hack/. 。他の人がそれを使用していて、うまく機能しているようで良かったです。現時点では、すべてのスクリプト タグの「バージョン番号」を増やすには、検索と置換よりも良い方法はないのではないかと思います。
で 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
最新の変更点
タグ ヘルパーを介した ASP.NET Core のキャッシュ無効化はこれを処理し、ファイルが変更されるまでブラウザーがキャッシュされたスクリプト/CSS を保持できるようにします。タグ ヘルパー asp-append-version="true" をスクリプト (js) タグまたはリンク (css) タグに追加するだけです。
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true"/>
Dave Paquette がキャッシュ無効化の良い例と説明をここに示しています (ページの下部) キャッシュバスティング
現在では、ファイル名の一部としてコンテンツ ハッシュ コードを生成して、ブラウザ、特に IE に JavaScript ファイルまたは CSS ファイルの再読み込みを強制することが一般的です。
例えば、
ベンダー。a7561fb0e9a071baadb9.js
主要。b746e3eb72875af2caa9.js
これは通常、webpack などのビルド ツールのジョブです。さらに詳しくはこちら 詳細 Webpack を使用している場合、誰かが試してみたい場合は。
最も簡単な解決策は?ブラウザにキャッシュをまったくさせないでください。現在の時刻 (ミリ秒単位) をクエリとして追加します。
(まだベータ版なので、パフォーマンスを最適化していないことについては合理的な理由が考えられます。ただし、YMMVはここにあります。)
を使用する利点 file.js?V=1
を超えて fileV1.js
複数のバージョンの JavaScript ファイルをサーバーに保存する必要がないということです。
私が見ている問題 file.js?V=1
新しいバージョンのライブラリ ユーティリティを使用すると、別の JavaScript ファイルに依存コードが壊れる可能性があるということです。
下位互換性のために、使用する方がはるかに良いと思います jQuery.1.3.js
新しいページには既存のページに使用させます jQuery.1.1.js
, 必要に応じて、古いページをアップグレードする準備ができるまで。
簡単な方法が 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]
asp.net mvcでは次のように使用できます @DateTime.UtcNow.ToString() js ファイルのバージョン番号。バージョン番号は日付に応じて自動的に変更され、クライアントのブラウザに js ファイルを自動的に更新させます。私はこの方法を使用していますが、うまくいきました。
<script src="~/JsFilePath/JsFile.js?v=@DateTime.UtcNow.ToString()"></script>
以下は私にとってうまくいきました:
<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>