Como posso especificar uma ordem de inclusão explícita de ScriptBundle?

Eu estou tentando o recurso MVC4 System.Web.Optimization 1.0 ScriptBundle .

Eu tenho a seguinte configuração:

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); } } 

e a seguinte visão:

  

onde BundlePaths.CanvasScripts é "~/bundles/scripts/canvas" . Isso renderiza isso:

  

Até aí tudo bem, exceto que o ~/Scripts/Shared/achievements.js é o primeiro script na fonte agrupada. Depende de cada script incluído antes no ScriptBundle . Como posso garantir que ele respeita a ordem na qual adiciono instruções de inclusão ao pacote?

Atualizar

Este era um aplicativo relativamente novo da ASP.NET MVC 4, mas referenciava o pacote de pré-lançamento da estrutura de otimização. Eu removi e adicionei o pacote RTM em http://nuget.org/packages/Microsoft.AspNet.Web.Optimization . Com a versão RTM com debug = true em web.config, @Scripts.Render("~/bundles/scripts/canvas") renderiza as tags de script individuais na ordem correta.

Com debug = false no web.config, o script combinado tem o script achievements.js primeiro, mas como é uma definição de function (construtor de object) que é chamada posteriormente, ele é executado sem erro. Talvez o minidificador seja inteligente o suficiente para descobrir dependencies?

Eu também tentei a implementação do IBundleOrderer que o Darin Dimitrov sugeriu com o RTM com as duas opções de debugging e se comportou da mesma forma.

Portanto, a versão minificada não está na ordem esperada, mas funciona.

    Eu não estou vendo esse comportamento nos bits RTM, você está usando os bits do Microsoft ASP.NET Web Optimization Framework 1.0.0: http://nuget.org/packages/Microsoft.AspNet.Web.Optimization ?

    Eu usei uma reprodução semelhante à sua amostra, baseada em um novo site de aplicativos de Internet MVC4.

    Eu adicionei ao 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); 

    E então na página de índice padrão, eu adicionei:

      

    E verifiquei que no javascript minificado para o pacote, o conteúdo de achievements.js foi depois modernizr …

    Você pode escrever um IBundleOrderer pacote personalizado ( IBundleOrderer ) que garantirá que os pacotes sejam incluídos na ordem em que você os registrou:

     public class AsIsBundleOrderer : IBundleOrderer { public virtual IEnumerable OrderFiles(BundleContext context, IEnumerable files) { return files; } } 

    e depois:

     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); } } 

    e na sua opinião:

     @Scripts.Render("~/bundles/scripts/canvas") 

    Obrigado Darin. Eu adicionei um método de extensão.

     internal class AsIsBundleOrderer : IBundleOrderer { public virtual IEnumerable OrderFiles(BundleContext context, IEnumerable files) { return files; } } internal static class BundleExtensions { public static Bundle ForceOrdered(this Bundle sb) { sb.Orderer = new AsIsBundleOrderer(); return sb; } } 

    Uso

     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()); 

    Atualizada a resposta fornecida pelo SoftLion para lidar com mudanças no MVC 5 (BundleFile vs FileInfo).

     internal class AsIsBundleOrderer : IBundleOrderer { public virtual IEnumerable OrderFiles(BundleContext context, IEnumerable files) { return files; } } internal static class BundleExtensions { public static Bundle ForceOrdered(this Bundle sb) { sb.Orderer = new AsIsBundleOrderer(); return sb; } } 

    Uso:

      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()); 

    Eu gosto de usar a syntax fluente, mas também funciona com uma única chamada de método e todos os scripts são passados ​​como parâmetros.

    Você deve poder definir o pedido com a ajuda do BundleCollection.FileSetOrderList. Dê uma olhada neste post: http://weblogs.asp.net/imranbaloch/archive/2012/09/30/hidden-options-of-asp-net-bundling-and-minification.aspx . O código na sua instância seria algo como:

     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); 

    Você deve considerar o uso do Cassete http://getcassette.net/ Ele suporta a detecção automática de dependencies de script com base nas referências de script encontradas dentro de cada arquivo.

    Se você preferir aderir à solução MS Web Optimization, mas gostar da idéia de organizar scripts com base em referências de script, leia o post do meu blog em http://blogs.microsoft.co.il/oric/2013/12/27/building-single -page-application-bundle-orderer /

    A resposta do @Darin Dimitrov funciona perfeitamente para mim, mas meu projeto está escrito em VB, então aqui está sua resposta convertida em 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 

    Para usá-lo:

     Dim scriptBundleMain = New ScriptBundle("~/Scripts/myBundle") scriptBundleMain.Orderer = New AsIsBundleOrderer() scriptBundleMain.Include( "~/Scripts/file1.js", "~/Scripts/file2.js" ) bundles.Add(scriptBundleMain)