Ordene manualmente os seus scripts via Bundles

A feature Bundles e Minification foi introduzida a partir da versão do ASP.NET MVC 4 e trouxe bastante praticidade, porém precisamos de um ajuste manual para obter a ordenação exata dos scripts.

Utilizar os Bundles da forma tradicional pode ocasionar alguns problemas na execução de nossos scripts devido ao seu padrão de ordenação. Encontrar a solução para estes problemas pode tomar algumas horas de trabalho se não observarmos corretamente o comportamento dos Bundles.

Um exemplo simples:
Para utilizar a biblioteca de globalização de validações “jquery.validate.globalize.js” certamente precisaremos da biblioteca “jquery.validate.js” e “globalize.js”, pois são dependências para que a validação funcione de forma globalizada. Portanto para o browser poder executar os métodos de “jquery.validate.globalize.js” é necessário ter carregado previamente a bibliotecas que são dependências.

Utilizando os Bundles de forma tradicional teríamos uma configuração parecida com o exemplo a seguir.

// Adicionando jQuery
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
            "~/Scripts/jquery-{version}.js"));

// Adicionando Validação, e Globalização
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
            "~/Scripts/jquery.validate.js",
            "~/Scripts/globalize.js",
            "~/Scripts/jquery.validate.globalize.js"));

E por consequência o código HTML gerado para interpretação do browser não seria o esperado.

Bundles Uncaught ReferenceError

Uncaught ReferenceError: Globalize is not defined

Este problema ocorreu por que o Bundle não gerou os scripts na ordem em que foram declarados como no código acima, pois sua ordenação padrão não respeita a ordem da declaração. Logo a biblioteca “jquery.validate.globalize.js” não encontrou sua dependência e não executou suas funções.

Existem algumas formas de resolver este problema, minha recomendação é criar uma classe de ordenação que respeita a ordem em que as bibliotecas foram declaradas. Esta classe pode ser criada no próprio arquivo “BundleConfig.cs” para manter a simplicidade da implementação.

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

E a forma de declaração do Bundle precisa ser modificada para fazer uso desta nova ordenação.

// Adicionando jQuery
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
            "~/Scripts/jquery-{version}.js"));

// Adicionando Validação, e Globalização
// Utilizando ordenação manual
var valBundle = new ScriptBundle("~/bundles/jqueryval").Include(
    "~/Scripts/jquery.validate.js",
    "~/Scripts/globalize.js",
    "~/Scripts/jquery.validate.globalize.js");

valBundle.Orderer = new AsIsBundleOrderer();

bundles.Add(valBundle);

Utilizamos algumas linhas a mais, porém garantimos a ordenação da forma que o browser precisa para poder executar tudo corretamente. O resultado é como o esperado.

Bundles Order Ok

Como podemos conferir é muito importante estar atento a este comportamento dos Bundles para evitar possíveis problemas e por consequência perder um tempo precioso de trabalho.

* Esta abordagem vale também para os StyleBundles que trabalham com CSS.

** Caso esteja trabalhando com o recurso de Minification este comportamento pode ocorrer ou não dependendo do cenário.


Se você estiver interessado em conhecer mais e aprender como desenvolver aplicações Web com arquitetura baseada em DDD, aplicando os princípios SOLID, diversos Design Patterns e escrevendo testes de unidade inscreva-se em meu curso:

Vamos continuar a troca de experiências, deixe seu comentário abaixo, se gostou e concorda com o artigo compartilhe com seus colegas para transmitirmos o conhecimento para o máximo de pessoas possíveis. ;)