...またはMicrosoftの完全に文書化されていないAPIに対して心配するのをやめてコードを書くことを学んだ方法。公式の実際の文書はありますかSystem.Web.Optimization
リリース? 「私は確かに見つけることができません。XMLドキュメントはありません。すべてのブログ投稿は、実質的に異なるRC APIを参照しています。 Anyhoo ..
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
オブジェクトを変更してもキャッシュはフラッシュされません-そのため、newアイテム(または、別の名前の新しいアイテム)のみが使用されます。
動作は奇妙に思えます...コレクションから何かを削除すると、キャッシュからも削除されます。しかし、そうではありません。このキャッシュをフラッシュし、そのバンドルが最初にアクセスされたときにキャッシュしたものではなく、BundleCollection
の現在の内容を使用する方法が必要です。
私はこれをどのように行うのでしょうか?
未知の目的を持つこのResetAll
メソッドがありますが、とにかく物事を壊しているだけです。
残念ながら、この機能は非常に急速に変化しており、ドキュメントの生成には多少の遅れがあり、ほぼすぐに時代遅れになる可能性があります。 Rickのブログ投稿 は最新のものであり、その間に現在の情報を広めるために、ここでも質問に答えようとしました。私たちは現在、常に最新のドキュメントがある公式codeplexサイトのセットアップを進めています。
次に、キャッシュからバンドルをフラッシュする方法の特定の問題について説明します。
要求されたバンドルURLから生成されたキーを使用して、ASP.NETキャッシュ内にバンドルされた応答を格納します。つまり、Context.Cache["System.Web.Optimization.Bundle:~/bundles/jquery"]
また、このバンドルを生成するために使用されたすべてのファイルとディレクトリに対するキャッシュの依存関係を設定します。したがって、基になるファイルまたはディレクトリのいずれかが変更されると、キャッシュエントリがフラッシュされます。
リクエストごとにBundleTable/BundleCollectionのライブ更新を実際にサポートしていません。完全にサポートされているシナリオは、アプリの起動時にバンドルが設定されることです(これにより、Webファームシナリオですべてが適切に機能します。あなたのコード例を見ると、特定のリクエストでバンドルコレクションを動的に変更しようとしているのでしょうか?あらゆる種類のバンドル管理/再構成には、すべてが正しくセットアップされたことを保証するために、appdomainのリセットを伴う必要があります。
そのため、アプリドメインをリサイクルせずにバンドル定義を変更しないでください。バンドル内の実際のファイルを自由に変更できます。ファイルは自動的に検出され、バンドルURLの新しいハッシュコードが生成されます。
同様の問題があります。
クラスBundleConfig
で、_BundleTable.EnableOptimizations = true
_を使用した場合の効果を確認しようとしていました。
_public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
BundleTable.EnableOptimizations = true;
bundles.Add(...);
}
}
_
すべてが正常に機能していました。
ある時点で、デバッグを行い、プロパティをfalseに設定しました。
jqueryのバンドル(最初のバンドル)が解決およびロードされないように思われたため(_/bundles/jquery?v=
_)、何が起こっているのか理解するのに苦労しました。
いくつかの宣誓の後、私は何とか整理できたと思いますか(?!)登録の最初にbundles.Clear()
とbundles.ResetAll()
を追加してみてください。そうすれば、作業が再開されます。
_public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Clear();
bundles.ResetAll();
BundleTable.EnableOptimizations = false;
bundles.Add(...);
}
}
_
EnableOptimizations
プロパティを変更する場合にのみ、これら2つのメソッドを実行する必要があることに気付きました。
更新:
さらに掘り下げてみると、_BundleTable.Bundles.ResolveBundleUrl
_と_@Scripts.Url
_にバンドルパスを解決する問題があるようです。
簡単にするために、いくつかの画像を追加しました。
最適化をオフにして、いくつかのスクリプトをバンドルしました。
同じバンドルが本体に含まれています。
_@Scripts.Url
_はバンドルの「最適化された」パスを提供し、_@Scripts.Render
_は適切なパスを生成します。
_BundleTable.Bundles.ResolveBundleUrl
_でも同じことが起こります。
私はVisual Studio 2010 + MVC 4 + Framework .Net 4.0を使用しています
Webファームのシナリオのためにこれを行わないというHao Kungの推奨事項を念頭に置いて、これを実行したいシナリオがたくさんあると思います。解決策は次のとおりです。
BundleTable.Bundles.ResetAll(); //or something more specific if neccesary
var bundle = new Bundle("~/bundles/your-bundle-virtual-path");
//add your includes here or load them in from a config file
//this is where the magic happens
var context = new BundleContext(new HttpContextWrapper(HttpContext.Current), BundleTable.Bundles, bundle.Path);
bundle.UpdateCache(context, bundle.GenerateBundleResponse(context));
BundleTable.Bundles.Add(bundle);
上記のコードはいつでも呼び出すことができ、バンドルは更新されます。これは、EnableOptimizationsがtrueまたはfalseの両方の場合に機能します。つまり、次のように、デバッグまたはライブシナリオで正しいマークアップがスローされます。
@Scripts.Render("~/bundles/your-bundle-virtual-path")
また、再構築せずにバンドルを更新すると問題が発生しました。理解すべき重要な事項は次のとおりです。
そのため、動的バンドリングを行っている場合、バンドルの仮想パスをファイルパスに基づいて作成するコードを作成できます。ファイルパスをハッシュし、そのハッシュをバンドルの仮想パスの最後に追加することをお勧めします。この方法では、ファイルパスが変更されると仮想パスも変更され、バンドルが更新されます。
私がこの問題を解決したコードは次のとおりです。
public static IHtmlString RenderStyleBundle(string bundlePath, string[] filePaths)
{
// Add a hash of the files onto the path to ensure that the filepaths have not changed.
bundlePath = string.Format("{0}{1}", bundlePath, GetBundleHashForFiles(filePaths));
var bundleIsRegistered = BundleTable
.Bundles
.GetRegisteredBundles()
.Where(bundle => bundle.Path == bundlePath)
.Any();
if(!bundleIsRegistered)
{
var bundle = new StyleBundle(bundlePath);
bundle.Include(filePaths);
BundleTable.Bundles.Add(bundle);
}
return Styles.Render(bundlePath);
}
static string GetBundleHashForFiles(IEnumerable<string> filePaths)
{
// Create a unique hash for this set of files
var aggregatedPaths = filePaths.Aggregate((pathString, next) => pathString + next);
var Md5 = MD5.Create();
var encodedPaths = Encoding.UTF8.GetBytes(aggregatedPaths);
var hash = Md5.ComputeHash(encodedPaths);
var bundlePath = hash.Aggregate(string.Empty, (hashString, next) => string.Format("{0}{1:x2}", hashString, next));
return bundlePath;
}
(StyleBundleまたはScriptBundle)から派生させ、コンストラクターにインクルードを追加せずにオーバーライドしてみましたか?
public override IEnumerable<System.IO.FileInfo> EnumerateFiles(BundleContext context)
これは動的スタイルシートに対して行い、EnumerateFilesはすべてのリクエストで呼び出されます。これはおそらく最大の解決策ではありませんが、機能します。
デッドスレッドを復活させることをおologiesびしますが、Umbracoサイトでバンドルキャッシュに関する同様の問題が発生し、ユーザーがバックエンドできれいなバージョンを変更したときにスタイルシート/スクリプトが自動的に縮小されるようにしました。
私がすでに持っていたコードは(スタイルシートのonSavedメソッドにありました):
BundleTable.Bundles.Add(new StyleBundle("~/bundles/styles.min.css").Include(
"~/css/main.css"
));
および(onApplicationStarted):
BundleTable.EnableOptimizations = true;
何を試しても、「〜/ bundles/styles.min.css」ファイルは変わらないようです。私のページの先頭で、元々スタイルシートを次のようにロードしていました。
<link rel="stylesheet" href="~/bundles/styles.min.css" />
ただし、これを次のように変更することで機能するようになりました。
@Styles.Render("~/bundles/styles.min.css")
Styles.Renderメソッドは、上記のHaoが説明したキャッシュキーであると推測しているファイル名の最後にクエリ文字列を取り込みます。
私にとっては、それはそれと同じくらい簡単でした。これが何時間もこれをグーグルしていて、数年前の投稿しか見つけられない私のような誰かを助けることを願っています!