Compartilhar via


Bundling no ASP.NET MVC: simplificando a manipulação de scripts em uma aplicação Web

O objetivo deste artigo é descrever o funcionamento do mecanismo conhecido como Bundling no ASP.NET MVC.

Introdução

O desenvolvimento de aplicações Web tem na utilização da linguagem JavaScript um de seus principais pilares. O surgimento de uma ampla variedade de recursos baseados em JavaScript tornou possível a construção de aplicações sofisticadas, com um destaque especial para a biblioteca jQuery (além de um incontável e diversificado número de plugins derivados desta última). Suportados pelos principais browsers na atualidade, funcionalidades implementadas em JavaScript e jQuery constituem presença praticamente certa em sistemas que procuram atender às mais variadas finalidades.

Muitas destas bibliotecas de scripts constituem exemplos de projetos de código aberto (jQuery não foge a esta regra), sendo mantidas por grupos de desenvolvedores espalhados ao redor do globo. Levando em consideração tais fatos, não é difícil de imaginar que com o decorrer do tempo aparecerão inúmeras versões para uma mesma biblioteca. Gerenciar cada uma destas versões pode então se transformar num grande problema, haja visto o fato de muitos arquivos de scripts serem referenciados diretamente em vários pontos ao longo de uma aplicação Web.

No caso específico do framework ASP.NET MVC na plataforma .NET, a solução para este tipo questão passa pelo uso de um recurso conhecido como Bundling. Introduzido a partir da versão 4.5 do ASP.NET, este mecanismo tem como características principais:

  • A possibilidade de combinar vários arquivos em uma simples unidade (basicamente, um novo arquivo gerado dinamicamente), simplificando desse modo a forma como scripts e folhas de estilo são referenciadas em um site MVC. Uma consequência direta disto está na diminuição da quantidade de requisições HTTP utilizadas na obtenção das diferentes partes que formam o conteúdo de um documento HTML (como arquivos CSS e de scripts), aumentando assim a performance no carregamento da página considerada;
  • Ainda no que diz respeito à performance no acesso a sites, o uso de Bundling em projetos MVC permite otimizar o conteúdo de scripts e folhas de estilo CSS em tempo de execução. Do ponto de vista prático, isto é conseguido ao descartar elementos desnecessários (como espaços e comentários) nos arquivos manipulados via Bundling. Este processo de redução no tamanho de arquivos CSS e de scripts é chamado de Minification;
  • A existência de uma funcionalidade capaz de determinar a versão mais recente de uma biblioteca de scripts, com base no nome dos diferentes arquivos que representam a mesma. Graças a este recurso, diferentes versões de uma biblioteca podem coexistir em uma aplicação (geralmente em um mesmo diretório), com o ASP.NET MVC assumindo sempre como default o release mais recente (caso este último venha a apresentar problemas, a simples remoção do arquivo correspondente fará com que o site utilize automaticamente a versão imediatamente anterior da biblioteca).

Este artigo tem por meta descrever o funcionamento do recurso Bundling do ASP.NET MVC, fazendo uso para isto de uma aplicação básica de testes. Manipulando duas diferentes versões de uma biblioteca simples de scripts, a ideia é demonstrar como tal mecanismo pode tornar mais simples e transparente a manipulação de códigos JavaScript em soluções MVC.

Exemplo de utilização do recurso Bundling

Para implementar a solução aqui demonstrada foram utilizados os seguintes recursos:

  • O Microsoft Visual Studio Professional 2013 Update 3 como IDE de desenvolvimento;
  • O .NET Framework 4.5.1;
  • O framework ASP.NET ASP.NET MVC 5.2.2 para a criação de uma Web Application.

O primeiro passo envolvendo a construção da aplicação proposta por este artigo será a criação do projeto TesteMVCBundling. Esta aplicação será do tipo “ASP.NET Web Application”, conforme indicado a seguir:

Selecionar então o template “Web API”, desabilitando ainda a utilização de mecanismos de autenticação:

A próxima ação consistirá em criar uma nova biblioteca de scripts chamada teste.bundle-1.0.0.js. O arquivo em questão deverá fazer parte da pasta “Scripts” do projeto TesteMVCBundling:

O código-fonte que deverá constar no arquivo teste.bundle-1.0.0.js é extremamente simples; um método exibirMensagemTeste exibirá um alerta/mensagem indicando a versão desta biblioteca (1.0.0):

function exibirMensagemTeste() {
    alert('Teste - versão 1.0.0');
}

A View Index.cshtml (ligada a HomeController) também precisará ser alterada, de forma a invocar o método exibirMensagemTeste durante o carregamento da página HTML correspondente. Para que isto seja possível, referenciar a biblioteca de scripts teste.bundle-1.0.0.js, além de implementar o método ready na seção “scripts”:

<div class="jumbotron">
    <h1>Bundling no ASP.NET MVC</h1>
    <p>
        <a href="http://go.microsoft.com/fwlink/?LinkId=301862"
           class="btn btn-primary btn-lg">Saiba mais »</a>
    </p>
</div>
 
<div style="padding: 80px;">
    <h3>
        Aplicação criada com o objetivo de demonstrar a utilização do
        recurso Bundling no ASP.NET MVC.
    </h3>
</div>
 
@section scripts{
 
    <script type="text/javascript"
            src="~/Scripts/teste.bundle-1.0.0.js"></script>
 
    <script type="text/javascript">
 
        $(document).ready(function () {
            exibirMensagemTeste();
        });
 
    </script>
 
}

Ao se executar o projeto a partir do Visual Studio, aparecerá uma mensagem como indicado na próxima figura:

Embora os ajustes descritos até este ponto sejam triviais dentro do desenvolvimento Web, a abordagem utilizada pode resultar em trabalho extra no caso de aplicações MVC mais sofisticadas.

Se por ventura um arquivo de scripts como teste.bundle-1.0.0.js for referenciado explicitamente em vários locais de um projeto, todas as estruturas que dependam do mesmo deverão ser alteradas (normalmente Views), de maneira que utilizem uma nova versão de tal biblioteca. Caso o release em questão apresente problemas, um novo esforço revertendo as modificações se fará então necessário.

Considerando a construção de aplicações Web através do ASP.NET MVC, a solução mais flexível para evitar todo este trabalho de codificação passa pela utilização do mecanismo conhecido como Bundling. Habilitar o uso deste recurso em um projeto MVC é um processo bem simples; isto será feito através da inclusão de uma nova versão da biblioteca “teste.bundle” na pasta “Scripts” do projeto TesteMVCBundling (arquivo teste.bundle-1.0.1.js):

O código correspondente ao arquivo teste.bundle-1.0.1.js está detalhado a seguir:

function exibirMensagemTeste() {
    alert('Teste - versão 1.0.1');
}

Ao invés de referenciar diretamente o arquivo teste.bundle-1.0.1.js, as alterações descritas adiante têm por objetivo conferir um comportamento dinâmico à aplicação frente a novas versões de uma biblioteca de scripts. Em termos práticos, os ajustes farão com que o projeto TesteMVCBundling seja capaz de determinar automaticamente qual dentre as versões da biblioteca “teste.bundle” é a mais recente.

O próximo ajuste envolve uma modificação na classe BundleConfig, a qual faz parte do arquivo BundleConfig.cs (localizada na pasta App_Start do projeto TesteMVCBundling):

A classe BundleConfig é criada automaticamente, ao se gerar um novo projeto baseado no ASP.NET MVC. Dentro do método RegisterBundles constarão uma série de declarações, as quais têm por objetivo registrar bibliotecas e folhas de estilo CSS utilizadas pela aplicação.

Para o exemplo aqui abordado, será preciso incluir dentro da operação RegisterBundles uma referência que aponte para a biblioteca biblioteca “teste.bundle”:

  • Este procedimento envolve uma chamada ao método Add a partir do objeto bundles, fornecendo como parâmetro a tal instrução uma instância do tipo ScriptBundle (namespace System.Web.Optimization);
  • O construtor da classe ScriptBundle recebe como parâmetro uma string, a qual representa um caminho virtual para acesso a um conjunto de arquivos (que podem ser scripts e/ou folhas de estilo);
  • Já no método Include de ScriptBundle devem ser indicados quais arquivos serão carregados (ao se encontrar uma declaração que aponte para o caminho virtual definido no passo anterior). O uso da expressão “{version}” informa ao engine do ASP.NET MVC a necessidade de se buscar a versão mais recente de um arquivo (considerando que o conjunto de caracteres substituídos por esta expressão corresponda a um número de versão). Opcionalmente, o caracter “*” pode ser utilizado ao invés de “{version}”.

Na próxima listagem é possível observar o código da classe BundleConfig já ajustado:

using System.Web;
using System.Web.Optimization;
 
namespace TesteMVCBundling
{
    public class  BundleConfig
    {
        public static  void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery-{version}.js"));
 
            bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                        "~/Scripts/jquery.validate*"));
 
            bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                        "~/Scripts/modernizr-*"));
 
            bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
                      "~/Scripts/bootstrap.js",
                      "~/Scripts/respond.js"));
 
            bundles.Add(new StyleBundle("~/Content/css").Include(
                      "~/Content/bootstrap.css",
                      "~/Content/site.css"));
 
            // Registrando a biblioteca teste-bundle
            bundles.Add(new ScriptBundle("~/bundles/teste_bundle").Include(
                        "~/Scripts/teste.bundle-{version}.js"));
             
            BundleTable.EnableOptimizations = true;
        }
    }
}

Por fim, a View Index.csthml precisará ser alterada para deixar de referenciar diretamente uma versão da biblioteca “teste.bundle”. Substituir para isto o uso da tag “script” por uma chamada ao método Render do objeto Scripts, indicando ainda o caminho virtual especificado na implementação da classe BundleConfig:

<div class="jumbotron">
    <h1>Bundling no ASP.NET MVC</h1>
    <p>
        <a href="http://go.microsoft.com/fwlink/?LinkId=301862"
           class="btn btn-primary btn-lg">Saiba mais »</a>
    </p>
</div>
 
<div style="padding: 80px;">
    <h3>
        Aplicação criada com o objetivo de demonstrar a utilização do
        recurso Bundling no ASP.NET MVC.
    </h3>
</div>
 
@section scripts{
 
    @Scripts.Render("~/bundles/teste_bundle")
 
    <script type="text/javascript">
 
        $(document).ready(function () {
            exibirMensagemTeste();
        });
 
    </script>
 
}

Executando mais uma vez o projeto TesteMVCBundling por meio do Visual Studio, será exibida a mensagem declarada na nova versão da biblioteca “teste.bundle”:

Conclusão

Conforme descrito neste artigo, o foco primário do mecanismo conhecido como Bundling no ASP.NET MVC está em melhorar a performance no carregamento de páginas Web. A possibilidade de uma aplicação ter seus arquivos de scripts atualizados de forma transparente (sem que isto implique em modificações em diversas Views) representa, sem sombra de dúvidas, outro grande benefício oferecido por este recurso.

Referências

ASP.NET MVC
http://www.asp.net/mvc

Bundling and Minification
http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification