Как я могу указать явный порядок включения ScriptBundle?
Я пробую система MVC4.Сеть.Оптимизация 1.0 ScriptBundle feature.
у меня есть следующие конфигурации:
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);
}
}
и следующий вид:
<script type="text/javascript" src="@Scripts.Url(BundlePaths.CanvasScripts)"></script>
здесь BundlePaths.CanvasScripts
- это "~/bundles/scripts/canvas"
. Он делает это:
<script type="text/javascript" src="/bundles/scripts/canvas?v=UTH3XqH0UXWjJzi-gtX03eU183BJNpFNg8anioG14_41"></script>
пока все хорошо, кроме ~/Scripts/Shared/achievements.js
является первым скриптом в комплекте источника. Это зависит от каждого сценария включенными в ScriptBundle
. как я могу гарантировать, что он соблюдает порядок, в котором я добавляю операторы include в пакет?
обновление
это было относительно новое ASP.NET приложение MVC 4, но оно ссылалось на пакет предварительной версии optimization framework. Я удалил его и добавил пакет RTM из http://nuget.org/packages/Microsoft.AspNet.Web.Optimization. с версией RTM с debug=true в web.config,@Scripts.Render("~/bundles/scripts/canvas")
отображает отдельные теги скрипта в правильном порядке.
С debug=false в интернете.конфиг, комбинированный скрипт имеет свои достижения.сначала JS-скрипт, но поскольку его определение функции (конструктор объектов), которое вызывается позже, выполняется без ошибок. Возможно, минификатор достаточно умен, чтобы выяснить зависимости?
я тоже пробовал IBundleOrderer
реализация, которую Дарин Димитров предложил с RTM с обоими вариантами отладки, и она вела себя одинаково.
таким образом, уменьшенная версия не в том порядке, который я ожидаю, но это работает.
7 ответов:
Я не вижу такого поведения на битах RTM, вы используете Microsoft ASP.NET Web Optimization Framework 1.0.0 bits:http://nuget.org/packages/Microsoft.AspNet.Web.Optimization?
я использовал аналогичное повторение для вашего образца, основанного на новом веб-сайте интернет-приложения MVC4.
я добавил в BundleConfig.RegisterBundles:
Bundle canvasScripts = new ScriptBundle("~/bundles/scripts/canvas") .Include("~/Scripts/modernizr-*") .Include("~/Scripts/Shared/achievements.js") .Include("~/Scripts/Shared/canvas.js"); bundles.Add(canvasScripts);
и затем на странице индекса по умолчанию я добавил:
<script src="@Scripts.Url("~/bundles/scripts/canvas")"></script>
и я проверил, что в минимизированный javascript для пакета, содержание достижений.js был после модернизации...
вы могли бы написать пользовательский пакет заказчика (
IBundleOrderer
), что обеспечит пакеты включены в порядке их регистрации:public class AsIsBundleOrderer : IBundleOrderer { public virtual IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files) { return files; } }
и затем:
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); } }
а на ваш взгляд:
@Scripts.Render("~/bundles/scripts/canvas")
спасибо Дарин. Я добавил метод расширения.
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; } }
использование
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());
обновлен ответ, предоставленный SoftLion для обработки изменений в 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; } }
использование:
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());
мне нравится использовать синтаксис fluent, но он также работает с одним вызовом метода и всеми скриптами, переданными в качестве параметров.
вы должны быть в состоянии установить порядок с помощью BundleCollection.FileSetOrderList. Посмотрите на это сообщение в блоге: http://weblogs.asp.net/imranbaloch/archive/2012/09/30/hidden-options-of-asp-net-bundling-and-minification.aspx . Код в вашем экземпляре будет что-то вроде:
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);
вы должны рассмотреть возможность использования кассеты http://getcassette.net/ он поддерживает автоматическое определение зависимостей сценариев на основе ссылок на сценарии, найденных внутри каждого файла.
Если вы предпочитаете придерживаться решения MS Web Optimization, но, как и идея организации скриптов на основе ссылок на Скрипты, вы должны прочитать мой пост в блогеhttp://blogs.microsoft.co.il/oric/2013/12/27/building-single-page-application-bundle-orderer/
@ ответ Дарина Димитрова отлично работает для меня, но мой проект написан на VB, поэтому вот его ответ, преобразованный в 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
использовать:
Dim scriptBundleMain = New ScriptBundle("~/Scripts/myBundle") scriptBundleMain.Orderer = New AsIsBundleOrderer() scriptBundleMain.Include( "~/Scripts/file1.js", "~/Scripts/file2.js" ) bundles.Add(scriptBundleMain)