1. ホーム
  2. c#

[解決済み] MVC4でBundleCollectionにキャッシュされたスクリプトバンドルを強制的にフラッシュさせる方法

2023-04-27 18:56:36

質問

... または どのように私は心配するのをやめ、Microsoftからの完全に文書化されていないAPIに対してコードを書くことを学んだか。 . 公式の System.Web.Optimization リリースの実際のドキュメントはありますか?'cuz 私は確かに何も見つけることができません、XMLドキュメントもありませんし、すべてのブログ記事は、実質的に異なるRC APIに言及しています。いずれにせよ...

私は、JavaScript の依存関係を自動的に解決するコードを書いており、それらの依存関係からオンザフライでバンドルを作成しています。すべてが素晴らしく機能しますが、スクリプトを編集したり、アプリケーションを再起動せずにバンドルに影響を与えるような変更を加えたりすると、変更が反映されません。そこで、開発で使用するために、依存関係のキャッシュを無効にするオプションを追加しました。

しかし、どうやら BundleTables は URL をキャッシュしています。 をキャッシュしているようですが、バンドルコレクションが変更された場合でも . 例えば、私自身のコードでは、バンドルを再作成したい場合、次のようにします。

// remove an existing bundle
BundleTable.Bundles.Remove(BundleTable.Bundles.GetBundleFor(bundleAlias));

// recreate it.
var bundle = new ScriptBundle(bundleAlias);

// dependencies is a collection of objects representing scripts, 
// this creates a new bundle from that list. 

foreach (var item in dependencies)
{
    bundle.Include(item.Path);
}

// add the new bundle to the collection

BundleTable.Bundles.Add(bundle);

// bundleAlias is the same alias used previously to create the bundle,
// like "~/mybundle1" 

var bundleUrl = BundleTable.Bundles.ResolveBundleUrl(bundleAlias);

// returns something like "/mybundle1?v=hzBkDmqVAC8R_Nme4OYZ5qoq5fLBIhAGguKa28lYLfQ1"

バンドルを削除したり、再作成するたびに を同じエイリアスで を削除しても、まったく何も起こりません。 bundleUrl から返される ResolveBundleUrl は、バンドルを削除 & 再作成する前と同じです。同じ」というのは、バンドルの新しいコンテンツを反映するためにコンテンツ ハッシュが変更されないという意味です。

編集 ...実は、もっとひどいんです。その バンドル自体 の外側にキャッシュされます。 Bundles コレクションの外にキャッシュされます。ブラウザがスクリプトをキャッシュするのを防ぐために、独自のランダムなハッシュを生成すると、ASP.NETは 古いスクリプト . ということは、どうやらバンドルを BundleTable.Bundles からバンドルを削除しても、実際には何もしないようです。

この問題を回避するために単にエイリアスを変更することができ、それは開発には問題ありませんが、それは各ページロード後にエイリアスを非推奨にするか、各ページロード時にサイズが大きくなるBundleCollectionを持つことを意味するので、私はそのアイデアが好きではありません。本番環境でこれをオンにしたままにしておくと、大惨事になるでしょう。

つまり、スクリプトが提供されるとき、それは実際の BundleTables.Bundles オブジェクトとは無関係にキャッシュされるようです。そのため、URLを再利用する場合、再利用する前に参照していたバンドルを削除していたとしても、キャッシュにあるものなら何でも応答します。 Bundles オブジェクトを変更してもキャッシュはフラッシュされません。 新しい アイテム (あるいはむしろ、異なる名前を持つ新しいアイテム) のみが使用されることになります。

この動作は奇妙に思えます...コレクションから何かを削除すると、キャッシュから削除されるはずです。しかし、そうではありません。このキャッシュをフラッシュする方法がなければなりません。 BundleCollection の現在の内容を使用するようにする方法があるはずです。

どのようにこれを行うか、何かアイデアはありますか?

次のようなものがあります。 ResetAll メソッドがありますが、これは目的が不明ですが、いずれにせよ物事を壊すだけなので、それとは違います。

どのように解決するのですか?

残念ながら、この機能はまだ非常に速く変化しており、ドキュメントを生成するのに多少の遅れがあり、ほとんどすぐに古くなってしまうことがあります。 Rick のブログ投稿 は最新のもので、私はここでも質問に答えるようにして、その間に最新の情報を広めるようにしています。 私たちは現在、常に最新のドキュメントを掲載した公式の codeplex サイトを立ち上げている最中です。

さて、キャッシュからバンドルをフラッシュする方法という特定の問題に関してです。

  1. 要求されたバンドルのURLから生成されたキーを使用して、バンドルされた応答をASP.NETキャッシュ内に保存します。 Context.Cache["System.Web.Optimization.Bundle:~/bundles/jquery"] また、このバンドルを生成するために使用されたすべてのファイルとディレクトリに対して、キャッシュの依存関係を設定します。 したがって、基礎となるファイルまたはディレクトリのいずれかが変更されると、キャッシュ エントリがフラッシュされます。

  2. 私たちは、リクエストごとの BundleTable/BundleCollection のライブアップデートをサポートしません。 完全にサポートされるシナリオは、アプリの起動時にバンドルを設定することです (これは、Web ファーム シナリオですべてが適切に動作するためです。そうしないと、間違ったサーバーに送られた場合、一部のバンドル リクエストが 404 になってしまいます)。 あなたのコード例を見ると、あなたは特定のリクエストで動的にバンドルコレクションを変更しようとしているのではないでしょうか? バンドル管理/再設定は、すべてが正しく設定されていることを保証するために、アプリドメインのリセットを伴う必要があります。

そのため、アプリのドメインを再利用せずにバンドル定義を変更することは避けてください。 バンドル内の実際のファイルを変更することは自由ですが、それは自動的に検出され、バンドル URL 用に新しいハッシュコードを生成するはずです。