1101

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

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

理想的には、このソリューションでは、ページにアクセスするたびにブラウザーにファイルの再読み込みを強制しないようにします。


John Millikinda5id の提案が役立つことがわかりました。これにはauto-versioningという用語があることがわかりました。

以下に新しい回答を投稿しました。これは、元のソリューションとジョンの提案を組み合わせたものです。

SCdFによって提案された別のアイデアは、偽のクエリ文字列をファイルに追加することです。(タイムスタンプを偽のクエリ文字列として自動的に使用する一部の Python コードが、piによって送信されました。)

ただし、ブラウザーがクエリ文字列を含むファイルをキャッシュするかどうかについては、いくつかの議論があります。(ブラウザにファイルをキャッシュして、今後のアクセスで使用するようにしたいことを思い出してください。ファイルが変更された場合にのみ、ファイルを再度取得する必要があります。)

4

56 に答える 56

483

このソリューションは PHP で記述されていますが、他の言語にも簡単に適用できます。

元の.htaccess正規表現は、json-1.3.js. 解決策は、末尾がちょうど 10 桁の場合にのみ書き直すことです。(10 桁は、2001 年 9 月 9 日から 2286 年 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 でも機能します。基本的に、動的に生成されないもの。

于 2008-09-23T03:07:49.363 に答える
219

シンプルなクライアント側のテクニック

一般に、キャッシングは良いことです... Web サイトを開発する際に自分で問題を修正するか、実稼働環境でキャッシュを制御しようとしているかに応じて、いくつかのテクニックがあります。

Web サイトへの一般的な訪問者は、サイトを開発しているときと同じ体験をすることはありません。平均的な訪問者がサイトにアクセスする頻度は低いため (Google または 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ヘッダーを変更することもできますが、上で書いたちょっとしたテクニックの方がおそらくはるかに簡単です。キャッシングは適切であるため、通常はその日付をかなり先の日付 (「Far-future Expires ヘッダー」) に設定し、上記の手法を使用して変更を強制します。

HTTP やこれらの要求がどのように行われるかについて詳しく知りたい場合は、Steve Souders 著の「High Performance Web Sites」が良い本です。これは、主題への非常に良い紹介です。

于 2008-09-23T04:04:57.150 に答える
115

Apache用の Google のmod_pagespeedプラグインは、自動バージョン管理を行います。それは本当に滑らかです。

Web サーバーから送信される途中で HTML を解析し (PHP、Ruby on Rails、Python、静的 HTML など、あらゆるもので動作します)、CSS、JavaScript、画像ファイルへのリンクを書き換えて、id コードを含めます。非常に長いキャッシュ制御を使用して、変更された URL でファイルを提供します。ファイルが変更されると、URL が自動的に変更されるため、ブラウザーは URL を再取得する必要があります。基本的には、コードを変更することなく機能します。途中でコードを縮小することさえあります。

于 2011-04-07T22:26:11.663 に答える
96

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

したがって、URLは次のようになります

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

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

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

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

于 2008-09-23T13:25:04.790 に答える
89

なぜ皆さん/ギャルがこのソリューションを実装するのに苦労しているのかわかりません。

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

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

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

filemtime()は、ファイルが変更されたタイムスタンプを返す PHP 関数です。

于 2013-01-26T10:53:34.730 に答える
57

?foo=1234CSS / JavaScriptのインポートの最後に置くだけで、1234を好きなように変更できます。例については、StackOverflowHTMLソースをご覧ください。

?とにかくリクエストでパラメータが破棄/無視され、新しいバージョンをロールアウトするときにその数を変更できるという考えがあります。


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

ただし、仕様のその部分に準拠するかどうかを決定するのはWebサーバーと、ユーザーが使用するブラウザーの両方です。とにかく、すぐに新しいバージョンを要求できるからです。

于 2008-09-23T03:12:49.427 に答える
43

これは「自動バージョン管理」と呼ばれると聞きました。最も一般的な方法は、静的ファイルの変更時刻をURLのどこかに含め、書き換えハンドラーまたはURL構成を使用してそれを取り除くことです。

参照:

于 2008-09-23T03:21:55.770 に答える
32
于 2015-08-03T20:09:42.697 に答える
16

使用しないでくださいfoo.css?version=1

ブラウザーは、GET 変数を含む URL をキャッシュすることは想定されていません。http://www.thinkvitamin.com/features/webapps/serving-javascript-fastによると、Internet Explorer と Firefox はこれを無視しますが、OperaSafariは無視しません! 代わりに、foo.v1234.cssを使用し、書き換えルールを使用してバージョン番号を取り除きます。

于 2008-09-23T06:02:44.853 に答える
12

RewriteRule は、最後にドット表記のバージョン管理を含む JavaScript または CSS ファイルの小さな更新が必要です。例: json-1.3.js

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

RewriteRule ^(.*)\.[^.][\d]+\.(css|js)$ $1.$2 [L]
于 2010-08-05T16:55:01.247 に答える
12

ここに純粋な 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 を追加できます。

于 2015-01-13T14:46:12.453 に答える
11

興味深い投稿。ここですべての回答を読んだことと、「偽の」クエリ文字列で問題が発生したことがないという事実を組み合わせて(誰もがこれを使用するのをためらう理由がわかりません)、解決策を推測します(Apache書き換えルールの必要性を取り除きます受け入れられた回答のように) CSSファイルの内容の短いハッシュを(ファイルの日時ではなく)偽のクエリ文字列として計算することです。

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

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

もちろん、datetime ソリューションは CSS ファイルを編集する場合にも機能しますが、ファイルの datetime ではなく、CSS ファイルの内容に関するものだと思います。なぜこれらが混同されるのでしょうか?

于 2009-06-24T23:20:10.143 に答える
11

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

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

バンドルには、最小化による初回ページ読み込み時のパフォーマンスの向上など、他にも利点があります。

于 2014-09-30T20:11:38.663 に答える
10

私の開発では、Chrome には優れたソリューションがあることがわかりました。

https://superuser.com/a/512833

開発者ツールを開いた状態で、更新ボタンを長押しして、「Empty Cache and Hard Reload」にカーソルを合わせたら離します。

これは私の親友であり、あなたが望むものを手に入れるための超軽量の方法です!

于 2015-07-24T19:12:57.190 に答える
8

彼の完璧な解決策をくれた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;
            }
        }
    }
}
于 2011-01-07T05:58:27.343 に答える
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>
于 2016-05-31T06:43:06.170 に答える
7

次の場所でファイルを入手できるとします。

/styles/screen.css

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

/styles/screen.css?v=1234

または、バージョン情報を追加できます。例:

/v/1234/styles/screen.css

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

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

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

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

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

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

于 2008-09-24T08:51:32.210 に答える
6

JavaScript / 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>
于 2008-09-23T03:23:48.480 に答える
6

最近、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 %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 ファイルに触れると、キャッシュの無効化が自動的にトリガーされます。非常にうまく機能し、オーバーヘッドは目立ちません。

于 2008-09-23T13:54:40.803 に答える
6

ASP.NET については、高度なオプション (デバッグ/リリース モード、バージョン) を使用して次のソリューションを提案します。

次の方法で JavaScript または CSS ファイルを含めます。

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

Global.JsPostfixGlobal.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();
    }
    ...
}
于 2013-08-03T13:28:49.630 に答える
6

次のように、CSS と JavaScript の URL に乱数を追加するだけです。

example.css?randomNo = Math.random()
于 2013-07-04T10:01:51.350 に答える
5

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;
于 2016-12-23T16:25:21.033 に答える
2

サーバーでの要求に応じて削除されるリソースURLでタイムスタンプベースまたはハッシュベースの差別化要因を使用するアプローチに問題があります。たとえば、スタイルシートへのリンクを含むページもキャッシュされる可能性があります。したがって、キャッシュされたページは古いバージョンのスタイルシートを要求する可能性がありますが、最新バージョンが提供され、要求しているページで機能する場合と機能しない場合があります。

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

于 2013-01-17T16:05:50.527 に答える
2

SilverStripe固有の回答は、 http://api.silverstripe.org/3.0/source-class-SS_Datetime.html#98-110を読んで解決しました:

これが、SilverStripe テンプレートを使用していて、ページにアクセスしたり更新したりするたびにキャッシュされた画像を強制的にリロードしようとしている人に役立つことを願っています。私の場合、一度しか再生されないため、キャッシュされた後に再生されなかった GIF アニメーションです。私のテンプレートでは、単に追加しました:

?$Now.Format(dmYHis)

をファイル パスの末尾に追加して、一意のタイム スタンプを作成し、ブラウザに強制的に新しいファイルとして処理させます。

于 2015-07-20T20:05:11.050 に答える
2

TomA の答えは正しいです。

以下のSteve Soudersが引用したように、「querystring」メソッドを使用するとキャッシュされません。

...人気のあるプロキシである Squid は、クエリ文字列を使用してリソースをキャッシュしません。

style.TIMESTAMP.css を使用するという TomA の提案は良いですが、内容が本当に変更された場合にのみ MD5 も変更されるため、MD5 の方がはるかに優れています。

于 2012-07-06T02:50:39.193 に答える
2

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

また、これは実行時 (またはファイル システムの変更時) にファイルごとに 1 回計算されるため、設計時またはビルド プロセス中に行うことはおかしなことではありません。

ASP.NET MVC を使用している場合は、こちらの他の回答でコードを確認できます。

于 2011-06-22T12:46:04.343 に答える
2

次のプロセスを実装することをお勧めします。

  • デプロイするたびに、CSS および JavaScript ファイルをバージョン管理します。次のようなもの: screen.1233.css (バージョン管理システムを使用している場合、番号は SVN リビジョンである可能性があります)

  • それらを縮小してロード時間を最適化する

于 2008-09-24T11:38:17.847 に答える
2

純粋な JavaScriptでのローカル開発に対してのみ、 script.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">
于 2018-02-11T02:25:30.003 に答える
2

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

詳細については 、アプリケーション キャッシュの使用を参照してください。

于 2014-09-16T15:09:15.363 に答える
1

SPA のソリューションを探しているときに、この質問にたどり着きました。SPA には、必要なすべてのファイルをリストしたindex.htmlファイルが 1 つしかありません。いくつかの手がかりを得ることができましたが、迅速かつ簡単な解決策を見つけることができませんでした。

最後に、発行プロセスの一部としてHTML/JavaScript のindex.htmlファイルを自動バージョン化するために必要な簡単なページ (すべてのコードを含む) を作成しました。それは完全に機能し、最後に変更された日付に基づいて新しいファイルのみを更新します。

Autoversion your SPA index.htmlで私の投稿を見ることができます。スタンドアロンの Windows アプリケーションもあります。

コードの中身は次のとおりです。

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");
}
于 2016-05-12T08:20:43.190 に答える
1

「SCdF によって提案されたもう 1 つのアイデアは、偽のクエリ文字列をファイルに追加することです。(偽のクエリ文字列としてタイムスタンプを自動的に使用する Python コードが pi によって提出されました。)ブラウザーがクエリ文字列を含むファイルをキャッシュするわけではありません (ブラウザーにファイルをキャッシュして、今後のアクセスで使用するようにします。ファイルが変更された場合にのみ、ファイルを再度フェッチするようにします)。偽のクエリ文字列で何が起こるか、私はその答えを受け入れません。」

<link rel="stylesheet" href="file.css?<?=hash_hmac('sha1', session_id(), md5_file("file.css")); ?>" />

ファイルをハッシュするということは、ファイルが変更されると、クエリ文字列が変更されることを意味します。そうでない場合は、そのままになります。各セッションもリロードを強制します。

オプションで、書き換えを使用して、ブラウザーに新しいURIであると認識させることもできます。

于 2013-03-29T13:51:04.680 に答える
1

ASP.NET Web サイトのもう 1 つの提案は、

  1. cache-control:max-age静的ファイルごとに異なる値を設定します。

  2. CSS および JavaScript ファイルの場合、サーバー上でこれらのファイルが変更される可能性が高いため、最小のcache-control:max-age値を 1 または 2 分または必要に応じて設定します。

  3. 画像の場合、 cache-control:max-age値として遠い日付(たとえば 360 日) を設定します。

  4. そうすることで、最初のリクエストを行うと、すべての静的コンテンツが200-OKレスポンスでクライアント マシンにダウンロードされます。

  5. それ以降のリクエストでは、2 分後に、CSS および JavaScript ファイルに対する304-Not Modifiedリクエストが表示され、CSS および JavaScript のバージョニングが回避されます。

  6. イメージ ファイルは、キャッシュの有効期限が切れるまでキャッシュ メモリから使用されるため、要求されません。

  7. 以下のweb.config構成を使用することで、上記の動作を実現できます。

    <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
        <staticContent>
            <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="00.00:01:00"/>
        </staticContent>
        <httpProtocol>
            <customHeaders>
                <add name="ETAG" value=""/>
            </customHeaders>
        </httpProtocol>
    </system.webServer>
    
    <location path="Images">
        <system.webServer>
            <staticContent>
                <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="180.00:00:00" />
            </staticContent>
        </system.webServer>
    </location>
    
于 2014-08-12T13:19:18.070 に答える
0

さて、次のようにJavaScriptファイルのバージョンに乱数を追加して、ページが読み込まれるたびにJavaScriptファイルのバージョンを変更することで、自分のやり方で機能させました。

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

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

<script src="file.js?version=<?php echo $random_number;?>"></script>
于 2016-08-21T02:59:01.733 に答える
0

これを行うための私の方法は、リンク要素をサーバー側に含めることです。

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

css-element.txt の内容は

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

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

于 2008-09-25T01:40:46.137 に答える
0

実装方法が異なる1つのソリューションがあります。上記のソリューションを使用します。

datatables?v=1

ファイルのバージョンを処理できます。これは、ファイルを変更するたびに、そのバージョンも変更することを意味します。しかし、それは適切な方法ではありません。

別の方法ではGUIDを使用しました。毎回ファイルをフェッチし、ブラウザのキャッシュから使用しないため、これも適切ではありませんでした。

datatables?v=Guid.NewGuid()

最良の方法である最後の方法は次のとおりです。

ファイルの変更が発生した場合は、バージョンも変更します。次のコードを確認してください。

<script src="~/scripts/main.js?v=@File.GetLastWriteTime(Server.MapPath("/scripts/main.js")).ToString("yyyyMMddHHmmss")"></script>

これにより、ファイルを変更すると LastWriteTime も変更されるため、ファイルのバージョンが変更され、次にブラウザを開いたときに、新しいファイルを検出してフェッチします。

于 2020-02-21T10:54:29.733 に答える
-1

jQueryを使用している場合は、乱数を追加する cache というオプションがあります。

これは私が知っている完全な答えではありませんが、時間を節約できるかもしれません。

于 2008-09-24T20:06:02.527 に答える
-2

JavaScript ファイルのもう 1 つの方法は、 jQueryをoption$.getScriptと組み合わせて使用​​することです。$.ajaxSetupcache: false

それ以外の:

<script src="scripts/app.js"></script>

以下を使用できます。

$.ajaxSetup({
  cache: false
});

$.getScript('scripts/app.js'); // GET scripts/app.js?_1391722802668
于 2014-02-06T21:43:23.157 に答える
-3

ファイル名を変更するとうまくいきます。しかし、それは通常、最も単純な解決策ではありません。

お気づきのように、'no-cache' の HTTP キャッシュ制御ヘッダーが常に機能するとは限りません。HTTP 1.1 仕様では、ユーザー エージェントが新しいコピーを要求するかどうかを決定するための余裕ができます。(ディレクティブの名前を見るだけでは直感的ではありません。キャッシュの実際の HTTP 1.1 仕様を読んでください...コンテキストではもう少し意味があります。)

一言で言えば、厳格なキャッシュ制御を使用したい場合

Cache-Control: no-cache, no-store, must-revalidate

応答ヘッダーに。

于 2008-09-23T05:54:51.393 に答える
-3

最も簡単な方法は、PHP ファイル読み取り機能を利用することです。PHP にファイルの内容をタグにエコーさせるだけです。

<?php
//Replace the 'style.css' with the link to the stylesheet.
echo "<style type='text/css'>".file_get_contents('style.css')."</style>";
?>

PHP 以外のものを使用している場合、言語によっていくつかのバリエーションがありますが、ほとんどすべての言語にはファイルの内容を出力する方法があります。適切な場所 (セクション内) に配置すると、ブラウザーに依存する必要がなくなります。

于 2011-11-03T17:34:42.217 に答える