O advento de frameworks baseados em JavaScript como AngularJS, Node.js e Knockout tem transformado a forma como aplicações Web são construídas. O desenvolvimento de soluções client-side sofisticadas é uma tendência crescente, sendo que este tipo de atividade tem priorizado questões como responsividade, produtividade e facilidade de manutenção.

Considerando especificamente o quesito produtividade, diversas ferramentas foram concebidas por desenvolvedores e comunidades com o intuito de simplificar a manipulação de arquivos de script e folhas de estilo CSS. A utilização de tais recursos vem aumentando significativamente dentro da programação client-side, com inúmeras opções gratuitas agilizando o processo de implementação de aplicações.

Não deixe de conferir o Checklist Programador .NET. A forma mais fácil de se tornar um expert em .NET.

Ao invés de se restringir à simples cópia de arquivos, algumas destas soluções foram bem além. Existe hoje todo um processo de build envolvendo scripts e arquivos CSS, sendo que o mesmo engloba tarefas como:

  • Bundling: consiste na combinação de vários arquivos em uma simples unidade (no caso um novo arquivo gerado dinamicamente). Como consequência direta deste procedimento ocorrerá uma diminuição da quantidade de requisições HTTP utilizadas na obtenção das diferentes partes que formam o conteúdo de um documento HTML (geralmente arquivos CSS e de scripts), com um considerável aumento na performance de carregamento de uma página que empregue tal técnica;
  • Minification: prática que envolve a eliminação em tempo de execução de itens desnecessários como espaços e comentários em arquivos CSS ou de scripts, também contribuindo para uma maior performance no carregamento de formulários HTML;
  • Determinar qual versão de uma biblioteca de scripts será utilizada: permite configurar o build de uma aplicação Web para que seja usado o release estável mais recente para um plugin jQuery, com o download automático dos arquivos necessários por exemplo;
  • A possibilidade de execução automática de ferramentas para verificação de código JavaScript, tais como JSHint e JSLint;
  • O uso de pré-processadores de CSS como LESS e SASS, mecanismos estes que viabilizam a utilização de variáveis, funções e mixins (agrupamentos de propriedades) em folhas de estilo.

Dentre as ferramentas mais populares na atualidade para a manipulação de arquivos de scripts e CSS, é possível destacar:

  • O Bower, gerenciador empregado na instalação e restauração de pacotes client-side (arquivos CSS e de scripts);
  • Os task runners Grunt e Gulp. Ambos fazem uso de arquivos de configuração com uma sintaxe baseada em JavaScript, sendo utilizados na automação de tarefas envolvendo a manipulação de scripts e CSS;
  • O npm (sigla de “Node Package Manager”). Embora seja um gerenciador de pacotes concebido inicialmente para a plataforma Node.js, esta ferramenta representa o ambiente a partir do qual outras soluções como Bower, Grunt e Gulp são executadas.

Algumas das funcionalidades aqui citadas foram incorporadas de forma nativa ao framework ASP.NET MVC 4, tais como Bundling, Minification e meios para determinar qual versão de uma biblioteca de scripts específica será utilizada (não existia porém uma funcionalidade para download automático dos arquivos correspondentes). Há casos inclusive em que bibliotecas de script poderiam ser baixadas e incorporadas a um projeto a partir do próprio utilitário NuGet.
Como não é difícil imaginar, a Microsoft observou com atenção a toda esta movimentação que vem acontecendo no desenvolvimento front-end. O Visual Studio 2013 conta com extensões que tornam possível o uso das ferramentas Bower, Grunt e npm, de maneira a facilitar o gerenciamento de recursos client-side em aplicações ASP.NET. Já no Visual Studio 2015 Preview este suporte é nativo, com a IDE incorporando estas soluções open source no controle de arquivos CSS e de scripts.

O objeto deste artigo é a utilização conjunta do Bower, Grunt e npm na manipulação de bibliotecas de scripts a partir do Visual Studio 2015, apresentando para isto um exemplo que será detalhado na próxima seção. Importante frisar que o mecanismo de Bundling existente em versões anteriores não está mais disponível com o lançamento do ASP.NET 5 e do ASP.NET MVC 6, dada a capacidade das ferramentas de automação mencionadas em substituir plenamente as funcionalidades oferecidas originalmente.

Exemplo envolvendo o gerenciamento de scripts no Visual Studio 2015

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

  • O Microsoft Visual Studio Ultimate 2015 Preview como IDE de desenvolvimento;
  • O .NET Framework 4.5.3;
  • O framework ASP.NET 5 para a criação de uma Web Application;
  • O plugin autoNumeric;
  • As ferramentas Bower, npm e Grunt integradas ao Visual Studio.

O projeto TesteVS2015Scripts será do tipo “ASP.NET Web Application” (Figura 1), sendo gerado a partir da seleção do template “ASP.NET 5 Starter Web” (Figura 2). Nesta aplicação MVC um usuário poderá informar seu peso e altura, com estes dados servindo de base para o cálculo de seu IMC (Índice de Massa Corpórea).

A intenção com este exemplo é detalhar de que forma acontece o gerenciamento de scripts no Visual Studio 2015, empregando para tanto os utilitários de automação aqui discutidos (Bower, npm e Grunt). Através destas ferramentas a biblioteca autoNumeric será incorporada ao projeto TesteVS2015Scripts, sem que isto implique na necessidade de uso do NuGet ou, mesmo, no download manual do plugin e posterior inclusão do mesmo na solução.

Criando a aplicação
 de testes no Visual Studio 2015

Figura 1. Criando a aplicação de testes no Visual Studio 2015

Selecionando o
 template para a criação da aplicação ASP.NET 5

Figura 2. Selecionando o template para a criação da aplicação ASP.NET 5

Analisando a estrutura do projeto criado via Solution Explorer (Figura 3), é possível observar a presença dos seguintes elementos:

  • A pasta wwwroot, em que constarão itens estáticos como documentos HTML, arquivos de scripts e folhas de estilo CSS dos quais a aplicação depende. Arquivos gerados através de processos como bundling, minification ou a partir de pré-processadores como LESS e SASS também serão transferidos para este local;
  • O item Dependencies, no qual estão declaradas as dependências manipuladas através das ferramentas Bower (pacotes client-side utilizados pelo projeto) e NPM (packages utilizados na execução do Grunt como task runner);
  • O item References, que engloba os pacotes .NET usados pela aplicação e que são manipulados a partir do utilitário NuGet;
  • Pastas como “Controllers”, “Models” e “Views”, estruturas típicas de uma aplicação MVC;
  • O arquivo config.json, que contém configurações diversas e substitui o Web.config presente em projetos criados em versões anteriores do ASP.NET;
  • O arquivo project.json, no qual estão definições e configurações gerais de uma aplicação (como pacotes do NuGet). Este documento substitui os arquivos com extensão .csproj (no caso de uma aplicação baseada no uso de C#);
  • O arquivo bower.json, em que estão declaradas as dependências de pacotes client-side manipuladas por meio da ferramenta Bower;
  • O arquivo package.json, no qual devem ser indicados os packages manipulados a partir do npm (basicamente, os pacotes necessários para a execução do utilitário Grunt);
  • O arquivo gruntfile.js, em que instruções JavaScript definem as tarefas a serem executas pela ferramenta Grunt.

Estrutura do
 projeto TesteVS2015Scripts

Figura 3. Estrutura do projeto TesteVS2015Scripts

Para incorporar a biblioteca autoNumeric ao projeto será necessário, primeiramente, alterar o arquivo bower.json de maneira que no mesmo conste o pacote correspondente. A execução do Bower será possível graças a tarefas configuradas para processamento via Grunt, além da utilização desta última ferramenta estar atrelada ao npm.

Na Listagem 1 está o conteúdo do arquivo package.json, com os pacotes que serão gerenciados via npm.

Listagem 1. Arquivo package.json


{
    "version": "0.0.0",
    "name": "TesteVS2015Scripts",
    "devDependencies": {
        "grunt": "^0.4.5",
        "grunt-bower-task": "^0.4.0"
    }
}

Já as instruções que definem o arquivo gruntfile.js encontram-se na Listagem 2. Dentre as ações a serem executadas está a instalação do Bower, além do carregamento de scripts que serão obtidos a partir desta ferramenta. Nas configurações para uso do utilitário Bower também está o diretório para onde serão copiados os pacotes de scripts da aplicação (wwwroot/lib).

Listagem 2. Arquivo gruntfile.json


module.exports = function  (grunt) {
     grunt.initConfig({
         bower: {
             install: {
                 options: {
                    targetDir: "wwwroot/lib",
                    layout: "byComponent",
                    cleanTargetDir: false
                 }
             }
        }
    });
 
    grunt.registerTask("default", ["bower:install"]);
    grunt.loadNpmTasks("grunt-bower-task");
};

OBSERVAÇÃO: O código dos arquivos package.json, gruntfile.js e bower.json é gerado automaticamente durante a criação de um projeto ASP.NET 5.

A inclusão de novos packages no arquivo bower.json é facilitada graças ao suporte oferecido pelo IntelliSense. Acessando informações de um repositório que contém os plugins suportados pelo Bower este recurso irá listar os diversos pacotes disponíveis, bem como as versões mais recentes dos mesmos (como indicado na Figura 4). Este mesmo tipo de funcionalidade existe para a edição do arquivo package.json, o qual contém as configurações a serem definidas para o utilitário npm.

Na seção exportsOverride do arquivo bower.json será necessário listar ainda quais arquivos do plugin autoNumeric serão carregados dentro da pasta wwwroot (no caso específico desta biblioteca, apenas o script autoNumeric.js). Na Listagem 3 encontram-se todas as mudanças realizadas em bower.json; outras dependências como o Bootstrap e jQuery já haviam sido registradas anteriormente, durante a criação do projeto TesteVS2015Scripts.

Utilizando o
 IntelliSense durante a edição do arquivo bower.json

Figura 4. Utilizando o IntelliSense durante a edição do arquivo bower.json

Listagem 3. Arquivo bower.json


{
    "name":  "TesteVS2015Scripts",
    "private":  true,
    "dependencies":  {
        "bootstrap": "~3.0.0",
        "jquery": "~1.10.2",
        "jquery-validation": "~1.11.1",
        "jquery-validation-unobtrusive": "~3.2.2",
        "autoNumeric": "~1.9.26"
    },
    "exportsOverride": {
        "bootstrap": {
            "js": "dist/js/*.*",
            "css": "dist/css/*.*",
            "fonts": "dist/fonts/*.*"
        },
        "jquery": {
            "js": "jquery.{js,min.js,min.map}"
        },
        "jquery-validation": {
            "": "jquery.validate.js"
        },
        "jquery-validation-unobtrusive": {
            "": "jquery.validate.unobtrusive.{js,min.js}"
        },
        "autoNumeric": {
            "js": "autoNumeric.js"
        }
    }
}

OBSERVAÇÃO: as versões de pacotes manipulados através do utilitário Bower seguem um conceito conhecido como versionamento semântico (em inglês “semantic versioning”), com três seções que se dividem em major version, minor version e patch (cada uma destas partes é separada por um ponto). O uso do símbolo “^” (circunflexo) antes de um número de versão (como em “^1.10”) é uma instrução para se utilizar um release que corresponda no mínimo à minor version especificada, além da obrigatoriedade de se coincidir com o valor da major version. Já o uso do símbolo “~” (til) como em “~1.10.2” determina a utilização de qualquer patch igual ou superior a 2 (considerando as versões 1.10 de uma biblioteca). A indicação de um valor como “1.10.2” sem nenhum símbolo precedente representa o uso específico de uma versão (desconsiderando assim futuros releases).

Verificando a estrutura do projeto TesteVS2015Scripts dentro do Solution Explorer, será possível constatar que o plugin autoNumeric ainda não foi instalado (Figura 5). A fim de realizar este procedimento, acionar com o botão direito do mouse o item “Bower” em “Dependencies” e selecionar a opção “Restore Packages” (Figura 6).

Plugin autoNumeric
 ainda não instalado

Figura 5. Plugin autoNumeric ainda não instalado

Instalando o plugin
 autoNumeric através do Bower

Figura 6. Instalando o plugin autoNumeric através do Bower

Na janela “Output” aparecerão então as diversas ações executadas pela ferramenta Bower, de forma a incorporar a biblioteca autoNumeric a esta aplicação de exemplo (Figura 7). Analisando novamente a estrutura do projeto TesteVS2015Scripts, já será possível constatar que o plugin autoNumeric foi corretamente instalado (Figura 8).

Instalando o plugin
 autoNumeric através do Bower

Figura 7. Instalando o plugin autoNumeric através do Bower

Plugin autoNumeric já
 instalado

Figura 8. Plugin autoNumeric já instalado

Os scripts dos quais uma aplicação depende também podem ser atualizados ou, mesmo, restaurados a partir da funcionalidade Task Runner Explorer. Para visualizar a janela correspondente clicar com o botão direito do mouse sobre o arquivo gruntfile.js, acionando em seguida a opção “Task Runner Explorer” (Figura 9). Este recurso também pode ser acessado a partir do menu View > Other Windows > Task Runner Explorer.

Acessando o Task
 Runner Explorer

Figura 9. Acessando o Task Runner Explorer

Com a janela “Task Runner Explorer” ativa, clicar desta vez com o botão direito mouse sobre o item “bower” e selecionar a opção Run (Figura 10). As tarefas configuradas para a ferramenta Bower serão então executadas (com base nas instruções definidas no arquivo gruntfile.js), com um prompt exibindo o resultado deste processo (Figura 11).

Restaurando packages via Task Runner Explorer

Figura 10. Restaurando packages via Task Runner Explorer

Resultado da
 execução de uma tarefa no Task Runner Explorer

Figura 11. Resultado da execução de uma tarefa no Task Runner Explorer

É possível ainda vincular a execução de tarefas especificadas no arquivo gruntfile.js a eventos que aconteçam na IDE do Visual Studio. Uma possibilidade seria executar a restauração de pacotes do Bower antes do build do projeto TesteVS2015Scripts: para que isto aconteça acionar a task “bower” com o botão direito do mouse, selecionando em seguida a opção “Bindings” e, por último, o item “Before Build” (Figura 12).

A realização deste procedimento fará com que a cada novo build os diversos pacotes configurados em bower.json sejam restaurados/atualizados. Este tipo de comportamento é extremamente útil quando da utilização de pré-processadores como LESS e SASS, uma vez que permitirá a geração dos arquivos CSS no formato esperado para o deployment de uma aplicação.

Atrelando a
 execução de uma tarefa a um evento da IDE

Figura 12. Atrelando a execução de uma tarefa a um evento da IDE

Como último passo será necessário alterar a View Index.cshtml, de forma a implementar a funcionalidade para cálculo do IMC. Conforme mencionado anteriormente, serão criados campos para preenchimento do peso e altura utilizando máscaras geradas pelo plugin autoNumeric.

Na Listagem 4 está o código referente à View Index.cshtml, sendo possível notar no mesmo:

  • Dois campos de texto (“peso” e “altura”) nos quais um usuário deverá informar os dados para o cálculo do IMC;
  • Uma section chamada “scripts”, em que constará o código responsável por calcular o IMC para uma determinada pessoa;
  • O código da section “scripts” inicia com uma referência para a biblioteca autoNumeric (que está localizada em wwwroot\lib\autoNumeric\js);
  • A função calcularIMC irá validar os campos de entrada, de forma a tornar obrigatório o preenchimento dos mesmos. Se o peso e a altura forem válidos, acontecerá o cálculo do IMC e o arredondamento deste valor para 2 casas decimais. Será verificado ainda em que faixa este índice se encontra, a fim de determinar situações de peso normal, sobrepeso ou ainda, peso abaixo do limite tolerável. Por fim, uma mensagem será exibida com o valor do IMC e o status decorrente deste indicador;
  • Já no método ready o plugin autoNumeric será acionado duas vezes, com o objetivo de criar a máscara de entrada para os campos de peso e altura.

Listagem 4. View Index.csthml


<div class="jumbotron">
    <h1>ASP.NET 5</h1>
    <p class="lead">
         Exemplo de aplicação MVC baseada no ASP.NET 5.
    </p>
    <p>
        <a href="http://asp.net/vnext"
            class="btn btn-primary  btn-lg">Saiba mais »</a>
    </p>
</div>
 
<h2>
    Teste  envolvendo o uso das ferramentas
     Bower, Grunt e nmp.
</h2>
 
<div style="padding: 20px;">
    <p class="lead">
         Peso (kg):
        <input id="peso" class="form-control  text-right" />
    </p>
    <p class="lead">
         Altura (m):
        <input id="altura" class="form-control  text-right" />
    </p>
    <a class="btn  btn-primary btn-lg"
       onclick="calcularIMC();">Calcular  IMC »</a>
</div>
 
@section scripts{
 
    <script type="text/javascript"
             src="~/lib/autoNumeric/js/autoNumeric.js"></script>
 
    <script type="text/javascript">
 
        function  calcularIMC() {
             var peso = $("#peso").val().replace(",", ".");
             if (peso == "") {
                 alert("Informe um valor para o Peso!");
                 return;
             }
 
             var  altura = $("#altura").val().replace(",", ".");
             if (altura == "") {
                 alert("Informe um valor para a Altura!");
                 return;
             }
 
             var IMC = peso / (altura * altura);
             IMC = Math.round(IMC * 100) / 100;
 
             var status;
             if (IMC < 18.5)
                 status = "Abaixo do Peso Ideal";
             else if  (IMC > 25)
                 status = "Acima do Peso Ideal";
             else
                 status = "Peso Normal";
 
             alert("Valor do IMC: " + IMC + "\n\n" +
                  "Status:  " + status);
        }
 
         $(document).ready(function () {
             $("#peso").autoNumeric({
                 aSep: '',
                 aDec: ',',
                 mDec: '1',
                 vMin: '0.1',
                 vMax: '1000.0'
             });
 
             $("#altura").autoNumeric({
                 aSep: '',
                 aDec: ',',
                 mDec: '2',
                 vMin: '0.01',
                 vMax: '9.99'
             });
         });
 
    </script>
}

Teste da aplicação criada

Na Figura 13 é apresentada a tela inicial da aplicação TesteVS2015Scripts.

Tela
 inicial da aplicação TesteVS2015Scripts

Figura 13. Tela inicial da aplicação TesteVS2015Scripts

Uma vez informados o peso e a altura, acionar a opção “Calcular IMC”. Será exibida então uma janela com o resultado, como indicado na Figura 14.

Mensagem
 exibida após o cálculo do IMC

Figura 14. Mensagem exibida após o cálculo do IMC

O objetivo deste artigo foi demonstrar as principais mudanças envolvendo o uso de recursos client-side no Visual Studio 2015 e no ASP.NET 5. Ao deixar de lado o mecanismo de Bundling e simplificar a integração com ferramentas de terceiros (como Bower, Grunt e npm), a Microsoft buscou não apenas estar em sintonia com o aquilo que se encontra em voga no desenvolvimento Web. Tal iniciativa também procurou atrair mais profissionais de front-end para a plataforma ASP.NET, partindo do suporte a soluções utilizadas extensivamente pelos mesmos em outros projetos.

Importante ressaltar que ao aprofundar os conhecimentos sobre o funcionamento de soluções como Bower, Grunt e npm, um desenvolvedor terá ainda um maior controle na customização do processo de build em aplicações ASP.NET.

Espero que o conteúdo aqui apresentado possa ser útil.

Até uma próxima oportunidade!

Links

ASP.NET vNext
http://www.asp.net/vnext

JSHint
http://jshint.com/

JSLint
http://www.jslint.com/

LESS
http://lesscss.org/

SASS
http://sass-lang.com/

Bower
http://bower.io/

Grunt
http://gruntjs.com/

Gulp
http://gulpjs.com/

npm
https://www.npmjs.com/

AutoNumeric
http://www.decorplanit.com/plugin/