Wypróbowuję funkcję MVC4 System.Web.Optimization 1.0 ScriptBundle .
Mam następującą konfigurację:
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
// shared scripts
Bundle canvasScripts =
new ScriptBundle(BundlePaths.CanvasScripts)
.Include("~/Scripts/modernizr-*")
.Include("~/Scripts/json2.js")
.Include("~/Scripts/columnizer.js")
.Include("~/Scripts/jquery.ui.message.min.js")
.Include("~/Scripts/Shared/achievements.js")
.Include("~/Scripts/Shared/canvas.js");
bundles.Add(canvasScripts);
}
}
i następujący widok:
<script type="text/javascript" src="@Scripts.Url(BundlePaths.CanvasScripts)"></script>
gdzie BundlePaths.CanvasScripts
jest "~/bundles/scripts/canvas"
. Przedstawia to:
<script type="text/javascript" src="/bundles/scripts/canvas?v=UTH3XqH0UXWjJzi-gtX03eU183BJNpFNg8anioG14_41"></script>
Jak na razie dobrze, z wyjątkiem ~/Scripts/Shared/achievements.js
pierwszego skryptu w dołączonym źródle. Zależy to od każdego skryptu zawartego przed nim w ScriptBundle
. Jak mogę się upewnić, że przestrzega kolejności, w której dodam instrukcje include do pakietu?
Aktualizacja
Była to stosunkowo nowa aplikacja ASP.NET MVC 4, ale odwoływała się do pakietu wstępnego wersji platformy optymalizacji. Usunąłem go i dodałem pakiet RTM z http://nuget.org/packages/Microsoft.AspNet.Web.Optimization . W wersji RTM z debug = true w pliku web.config,@Scripts.Render("~/bundles/scripts/canvas")
renderuje poszczególne tagi skryptu we właściwej kolejności.
Z debug = false w web.config, połączony skrypt ma najpierw skrypt osiągnięć.js, ale ponieważ jest to definicja funkcji (konstruktor obiektu), która jest wywoływana później, działa bez błędów. Być może minifier jest wystarczająco inteligentny, aby znaleźć zależności?
Próbowałem też IBundleOrderer
implementację, którą Darin Dimitrov zasugerował w RTM z obiema opcjami debugowania i zachowywała się tak samo.
Tak więc zminimalizowana wersja nie jest w kolejności, której się spodziewam, ale działa.
Możesz napisać niestandardowego zamawiającego paczki (
IBundleOrderer
), który zapewni, że pakiety będą uwzględnione w zamówieniu, w którym je zarejestrujesz:public class AsIsBundleOrderer : IBundleOrderer { public virtual IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files) { return files; } }
i wtedy:
public class BundleConfig { public static void RegisterBundles(BundleCollection bundles) { var bundle = new Bundle("~/bundles/scripts/canvas"); bundle.Orderer = new AsIsBundleOrderer(); bundle .Include("~/Scripts/modernizr-*") .Include("~/Scripts/json2.js") .Include("~/Scripts/columnizer.js") .Include("~/Scripts/jquery.ui.message.min.js") .Include("~/Scripts/Shared/achievements.js") .Include("~/Scripts/Shared/canvas.js"); bundles.Add(bundle); } }
i Twoim zdaniem:
@Scripts.Render("~/bundles/scripts/canvas")
źródło
Dziękuję Darin. Dodałem metodę rozszerzenia.
internal class AsIsBundleOrderer : IBundleOrderer { public virtual IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files) { return files; } } internal static class BundleExtensions { public static Bundle ForceOrdered(this Bundle sb) { sb.Orderer = new AsIsBundleOrderer(); return sb; } }
Stosowanie
bundles.Add(new ScriptBundle("~/bundles/jquery").Include( "~/Scripts/jquery-{version}.js", "~/Scripts/jquery-migrate-{version}.js", "~/Scripts/jquery.validate.js", "~/Scripts/jquery.validate.messages_fr.js", "~/Scripts/moon.jquery.validation-{version}.js", "~/Scripts/jquery-ui-{version}.js" ).ForceOrdered());
źródło
FileInfo
naBundleFile
w metodzie podpisu interfejs. Zmienili to.BundleFile
zajęć? Aby spakować osadzone zasoby, próbuję utworzyć instancję i wymaga to (konkretnego elementu potomnego)VirtualFile
parametru w swoim konstruktorze.Zaktualizowano odpowiedź dostarczoną przez SoftLion, aby obsłużyć zmiany w MVC 5 (BundleFile vs FileInfo).
internal class AsIsBundleOrderer : IBundleOrderer { public virtual IEnumerable<BundleFile> OrderFiles(BundleContext context, IEnumerable<BundleFile> files) { return files; } } internal static class BundleExtensions { public static Bundle ForceOrdered(this Bundle sb) { sb.Orderer = new AsIsBundleOrderer(); return sb; } }
Stosowanie:
bundles.Add(new ScriptBundle("~/content/js/site") .Include("~/content/scripts/jquery-{version}.js") .Include("~/content/scripts/bootstrap-{version}.js") .Include("~/content/scripts/jquery.validate-{version}") .ForceOrdered());
Lubię używać płynnej składni, ale działa również z pojedynczym wywołaniem metody i wszystkimi skryptami przekazywanymi jako parametry.
źródło
Powinieneś być w stanie ustawić kolejność za pomocą BundleCollection.FileSetOrderList. Spójrz na ten post na blogu: http://weblogs.asp.net/imranbaloch/archive/2012/09/30/hidden-options-of-asp-net-bundling-and-minification.aspx . Kod w Twojej instancji wyglądałby tak:
BundleFileSetOrdering bundleFileSetOrdering = new BundleFileSetOrdering("js"); bundleFileSetOrdering.Files.Add("~/Scripts/modernizr-*"); bundleFileSetOrdering.Files.Add("~/Scripts/json2.js"); bundleFileSetOrdering.Files.Add("~/Scripts/columnizer.js"); bundleFileSetOrdering.Files.Add("~/Scripts/jquery.ui.message.min.js"); bundleFileSetOrdering.Files.Add("~/Scripts/Shared/achievements.js"); bundleFileSetOrdering.Files.Add("~/Scripts/Shared/canvas.js"); bundles.FileSetOrderList.Add(bundleFileSetOrdering);
źródło
Powinieneś rozważyć użycie Cassette http://getcassette.net/ Obsługuje automatyczne wykrywanie zależności skryptów na podstawie odwołań do skryptów znajdujących się w każdym pliku.
Jeśli wolisz trzymać się rozwiązania MS Web Optimization, ale podoba Ci się pomysł porządkowania skryptów na podstawie odniesień do skryptów, przeczytaj mój post na blogu pod adresem http://blogs.microsoft.co.il/oric/2013/12/27/building-single -page-application-bundle-orderer /
źródło
Odpowiedź @Darina Dimitrova działa idealnie dla mnie, ale mój projekt jest napisany w VB, więc oto jego odpowiedź przekonwertowana na VB
Public Class AsIsBundleOrderer Implements IBundleOrderer Public Function IBundleOrderer_OrderFiles(ByVal context As BundleContext, ByVal files As IEnumerable(Of FileInfo)) As IEnumerable(Of FileInfo) Implements IBundleOrderer.OrderFiles Return files End Function End Class
Aby z niego skorzystać:
Dim scriptBundleMain = New ScriptBundle("~/Scripts/myBundle") scriptBundleMain.Orderer = New AsIsBundleOrderer() scriptBundleMain.Include( "~/Scripts/file1.js", "~/Scripts/file2.js" ) bundles.Add(scriptBundleMain)
źródło
Class 'AsIsBundleOrderer' must implement 'Function OrderFiles(context as ....)' for interface 'System.Web.Optimization.IBundleOrderer'
jakieś pomysły?