Я пробую функцию MVC4 System.Web.Optimization 1.0 ScriptBundle .
У меня такая конфигурация:
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, но оно ссылалось на предварительный пакет среды оптимизации. Я удалил его и добавил пакет RTM из http://nuget.org/packages/Microsoft.AspNet.Web.Optimization . В RTM-версии с debug = true в web.config @Scripts.Render("~/bundles/scripts/canvas")
отображаются отдельные теги сценария в правильном порядке.
Если debug = false в web.config, объединенный скрипт сначала содержит скрипт achievement.js, но, поскольку это определение функции (конструктор объекта), вызываемое позже, он выполняется без ошибок. Возможно, минификатор достаточно умен, чтобы вычислить зависимости?
Я также попробовал IBundleOrderer
реализацию, предложенную Дарином Димитровым в RTM, с обоими параметрами отладки, и она вела себя одинаково.
Таким образом, уменьшенная версия находится не в том порядке, в котором я ожидал, но она работает.
Вы можете написать собственный пакет orderer (
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());
источник
FileInfo
дляBundleFile
в сигнатуре метода интерфейса. Они изменили это.BundleFile
классе? Чтобы связать встроенные ресурсы, я пытаюсь создать его экземпляр, и для этого требуется параметр (конкретный дочерний элемент)VirtualFile
в его конструкторе.Обновлен ответ, предоставленный 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());
Мне нравится использовать свободный синтаксис, но он также работает с одним вызовом метода и всеми скриптами, переданными в качестве параметров.
источник
У вас должна быть возможность установить порядок с помощью 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);
источник
Вам следует рассмотреть возможность использования Cassette http://getcassette.net/. Он поддерживает автоматическое определение зависимостей скриптов на основе ссылок на скрипты, найденных внутри каждого файла.
Если вы предпочитаете использовать решение MS Web Optimization, но вам нравится идея организации сценариев на основе ссылок на сценарии, вам следует прочитать мое сообщение в блоге по адресу http://blogs.microsoft.co.il/oric/2013/12/27/building-single -страница-приложение-связка-заказчик /
источник
Ответ @Darin Dimitrov отлично работает для меня, но мой проект написан на 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)
источник
Class 'AsIsBundleOrderer' must implement 'Function OrderFiles(context as ....)' for interface 'System.Web.Optimization.IBundleOrderer'
идеи?