Compartilhar via


Usar Grunt no ASP.NET Core

Grunt é um executor de tarefas do JavaScript que automatiza a minificação de script, a compilação do TypeScript, as ferramentas de "lint" de qualidade do código, os pré-processadores CSS e praticamente qualquer tarefa repetitiva que precise ser feita para dar suporte ao desenvolvimento do cliente. O Grunt tem suporte total no Visual Studio.

Este exemplo usa um projeto vazio do ASP.NET Core como ponto de partida para mostrar como automatizar o processo de compilação do cliente do zero.

O exemplo concluído limpa o diretório de implantação de destino, combina arquivos do JavaScript, verifica a qualidade do código, condensa o conteúdo do arquivo do JavaScript e implanta na raiz do seu aplicativo Web. Utilizaremos os seguintes pacotes:

  • grunt: o pacote do executor de tarefas Grunt.

  • grunt-contrib-clean: um plug-in que remove arquivos ou diretórios.

  • grunt-contrib-jshint: um plug-in que analisa a qualidade do código do JavaScript.

  • grunt-contrib-concat: um plug-in que une arquivos em um único arquivo.

  • grunt-contrib-uglify: um plug-in que minifia o JavaScript para reduzir o tamanho.

  • grunt-contrib-watch: um plug-in que observa a atividade do arquivo.

Preparando o aplicativo

Para começar, configure um novo aplicativo Web vazio e adicione arquivos de exemplo do TypeScript. Os arquivos TypeScript são compilados automaticamente em JavaScript usando as configurações padrão do Visual Studio e serão nossa matéria-prima para processar usando Grunt.

  1. No Visual Studio, crie um novo ASP.NET Web Application.

  2. Na caixa de diálogo Novo Projeto do ASP.NET, selecione o modelo Vazio do ASP.NET Core e clique no botão OK.

  3. No Gerenciador de Soluções, examine a estrutura do projeto. A pasta \src inclui nós vazios wwwroot e Dependencies.

    solução Web vazia

  4. Adicione uma nova pasta chamada TypeScript ao diretório do projeto.

  5. Antes de adicionar arquivos, verifique se o Visual Studio tem a opção "compilar ao salvar" para arquivos TypeScript marcados. Navegue até Ferramentas>Opções>Editor de Texto>Typescript>Projeto:

    opções que definem a compilação automática de arquivos TypeScript

  6. Clique com o botão direito do mouse no diretório TypeScript e selecione Adicionar > Novo Item no menu de contexto. Selecione o item arquivo do JavaScript e dê um nome ao arquivo Tastes.ts (observe a extensão *.ts). Copie a linha de código TypeScript abaixo para o arquivo (quando você salvar, um novo arquivo Tastes.js aparecerá com a fonte JavaScript).

    enum Tastes { Sweet, Sour, Salty, Bitter }
    
  7. Adicione um segundo arquivo ao diretório TypeScript e dê a ele o nome Food.ts. Copie o código abaixo para o arquivo.

    class Food {
      constructor(name: string, calories: number) {
        this._name = name;
        this._calories = calories;
      }
    
      private _name: string;
      get Name() {
        return this._name;
      }
    
      private _calories: number;
      get Calories() {
        return this._calories;
      }
    
      private _taste: Tastes;
      get Taste(): Tastes { return this._taste }
      set Taste(value: Tastes) {
        this._taste = value;
      }
    }
    

Configurando o NPM

Em seguida, configure o NPM para fazer o download de grunt e grunt-tasks.

  1. No Gerenciador de Soluções, clique com o botão direito do mouse no projeto e, no menu de contexto, selecione Adicionar> Novo item. Selecione o item arquivo de configuração do NPM, deixe o nome padrão package.jsone clique no botão Adicionar.

  2. No arquivo package.json, dentro das chaves de objeto devDependencies, insira "grunt". Selecione grunt na lista IntelliSense e pressione a tecla Enter. O Visual Studio citará o nome do pacote grunt e adicionará dois-pontos. À direita dos dois-pontos, selecione a versão estável mais recente do pacote na parte superior da lista do IntelliSense (pressione Ctrl-Space se o Intellisense não aparecer).

    grunt Intellisense

    Observação

    O NPM usa controle de versão semântica para organizar dependências. O controle de versão semântica, também conhecido como SemVer, identifica pacotes com o esquema de numeração <principal>.< menor>.<patch>. O IntelliSense simplifica o controle de versão semântica mostrando apenas algumas opções comuns. O item superior na lista do IntelliSense (0.4.5 no exemplo acima) é considerado a versão estável mais recente do pacote. O símbolo de cursor (^) corresponde à versão principal mais recente e o til (~) corresponde à versão secundária mais recente. Consulte a referência do analisador de versão semver do NPM como um guia para a expressividade completa que o SemVer fornece.

  3. Adicione mais dependências para carregar pacotes grunt-contrib-* para clean, jshint, concat, uglify e watch, conforme mostrado no exemplo abaixo. As versões não precisam corresponder ao exemplo.

    "devDependencies": {
      "grunt": "0.4.5",
      "grunt-contrib-clean": "0.6.0",
      "grunt-contrib-jshint": "0.11.0",
      "grunt-contrib-concat": "0.5.1",
      "grunt-contrib-uglify": "0.8.0",
      "grunt-contrib-watch": "0.6.1"
    }
    
  4. Salve o arquivo package.json.

Os pacotes para cada item devDependencies serão baixados, juntamente com todos os arquivos necessários para cada pacote. Você pode encontrar os arquivos de pacote no diretório node_modules habilitando o botão Mostrar Todos os Arquivos no Gerenciador de Soluções.

grunt node_modules

Observação

Se precisar, você poderá restaurar manualmente as dependências no Gerenciador de Soluções clicando com o botão direito do mouse em Dependencies\NPM e selecionando a opção de menu Restaurar Pacotes.

restaurar pacotes

Configurando o Grunt

O Grunt é configurado usando um manifesto chamado Gruntfile.js que define, carrega e registra tarefas que podem ser executadas manualmente ou configuradas para serem executadas automaticamente com base em eventos no Visual Studio.

  1. Clique com o botão direito do mouse no projeto e selecione Adicionar>Novo item. Selecione o modelo de item Arquivo do JavaScript, altere o nome para Gruntfile.jse clique no botão Adicionar.

  2. Adicione o código a seguir a Gruntfile.js. A função initConfig define opções para cada pacote e o restante do módulo carrega e registra tarefas.

    module.exports = function (grunt) {
      grunt.initConfig({
      });
    };
    
  3. Dentro da função initConfig, adicione opções para a tarefa clean, conforme mostrado no exemplo Gruntfile.js abaixo. A tarefa clean aceita uma matriz de cadeias de caracteres do diretório. Essa tarefa remove arquivos de wwwroot/lib e remove todo o diretório /temp.

    module.exports = function (grunt) {
      grunt.initConfig({
        clean: ["wwwroot/lib/*", "temp/"],
      });
    };
    
  4. Abaixo da função initConfig, adicione uma chamada a grunt.loadNpmTasks. Isso tornará a tarefa executável no Visual Studio.

    grunt.loadNpmTasks("grunt-contrib-clean");
    
  5. Salvar Gruntfile.js. O arquivo deve ser semelhante à captura de tela abaixo.

    gruntfile inicial

  6. Clique com o botão direito do mouse em Gruntfile.js e selecione Explorer do Executor de Tarefas no menu de contexto. A janela Explorer do Executor de Tarefas será aberta.

    Menu do Explorer do Executor de Tarefas

  7. Verifique se clean é exibido em Tarefas no Explorer do Executor de Tarefas.

    Lista de Tarefas do Explorer do Executor de Tarefas

  8. Clique com o botão direito do mouse Limpar tarefa e selecione Executar no menu de contexto. Uma janela de comando exibe o progresso da tarefa.

    Explorer do executador de tarefas executando Limpar tarefa

    Observação

    Ainda não há arquivos ou diretórios para limpeza. Se desejar, você pode criá-los manualmente no Gerenciador de Soluções e, em seguida, executar Limpar tarefa como um teste.

  9. Na função initConfig, adicione uma entrada para concat usando o código abaixo.

    A matriz de propriedade src lista os arquivos a serem combinados, na ordem em que eles devem ser combinados. A propriedade dest atribui o caminho ao arquivo combinado que foi produzido.

    concat: {
      all: {
        src: ['TypeScript/Tastes.js', 'TypeScript/Food.js'],
        dest: 'temp/combined.js'
      }
    },
    

    Observação

    A propriedade all no código acima é o nome de um destino. Os destinos são usados em algumas tarefas Grunt para permitir vários ambientes de compilação. Você pode exibir os destinos internos usando o IntelliSense ou atribuir seus próprios.

  10. Adicione a tarefa jshint usando o código abaixo.

    O utilitário jshint code-quality é executado em todos os arquivos JavaScript encontrados no diretório temp.

    jshint: {
      files: ['temp/*.js'],
      options: {
        '-W069': false,
      }
    },
    

    Observação

    A opção "-W069" é um erro produzido por jshint quando o JavaScript usa sintaxe de colchete para atribuir uma propriedade em vez de notação de ponto, ou seja, Tastes["Sweet"] em vez de Tastes.Sweet. A opção desativa o aviso para permitir que o rest do processo continue.

  11. Adicione a tarefa uglify usando o código abaixo.

    A tarefa minifica o arquivo combined.js encontrado no diretório temp e cria o arquivo resultante em wwwroot/lib seguindo a convenção de nomenclatura padrão <nome do arquivo>.min.js.

    uglify: {
     all: {
       src: ['temp/combined.js'],
       dest: 'wwwroot/lib/combined.min.js'
     }
    },
    
  12. Na chamada para grunt.loadNpmTasks que carrega grunt-contrib-clean, inclua a mesma chamada para jshint, concat e uglify usando o código abaixo.

    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    
  13. Salvar Gruntfile.js. O arquivo deve ser semelhante o exemplo abaixo.

    exemplo completo de arquivo grunt

  14. Observe que a lista Tarefas do Explorer do Executor de Tarefas inclui tarefas clean, concat, jshint e uglify. Execute cada tarefa em ordem e observe os resultados em Gerenciador de Soluções. Cada tarefa deve ser executada sem erros.

    Explorer do executador de tarefas executando cada tarefa

    A tarefa concat cria um novo arquivo combined.js e o coloca no diretório temp. A tarefa jshint simplesmente é executada e não produz saída. A tarefa uglify cria um novo arquivo combined.min.js e o coloca em wwwroot/lib. Após a conclusão, a solução deve ser semelhante à captura de tela abaixo:

    gerenciador de soluções após todas as tarefas

    Observação

    Para obter mais informações sobre as opções de cada pacote, visite https://www.npmjs.com/ e pesquise o nome do pacote na caixa de pesquisa na página principal. Por exemplo, você pode pesquisar o pacote grunt-contrib-clean para obter um link de documentação que explica todos os seus parâmetros.

Todos juntos agora

Use o método Grunt registerTask() para executar uma série de tarefas em uma sequência específica. Por exemplo, para executar as etapas de exemplo acima na ordem clean -> concat -> jshint -> uglify, adicione o código abaixo ao módulo. O código deve ser adicionado ao mesmo nível que as chamadas loadNpmTasks(), fora de initConfig.

grunt.registerTask("all", ['clean', 'concat', 'jshint', 'uglify']);

A nova tarefa aparece no Explorer do Executor de Tarefas em Tarefas de Alias. Você pode clicar com o botão direito do mouse e executá-lo da mesma forma que faria com outras tarefas. A tarefa all executará clean, concat, jshint e uglify, na ordem.

tarefas do grunt de alias

Monitorando alterações

Uma tarefa watch fica de olho em arquivos e diretórios. A inspeção dispara tarefas automaticamente se detectar alterações. Adicione o código abaixo a initConfig para inspecionar alterações em arquivos *.js no diretório TypeScript. Se um arquivo JavaScript for alterado, watch executará a tarefa all.

watch: {
  files: ["TypeScript/*.js"],
  tasks: ["all"]
}

Adicione uma chamada ao loadNpmTasks() para mostrar a tarefa watch no Explorer do Executor de Tarefas.

grunt.loadNpmTasks('grunt-contrib-watch');

Clique com o botão direito do mouse na tarefa de inspeção no Explorer do Executor de Tarefas e selecione Executar no menu de contexto. A janela de comando que mostra a tarefa de inspeção em execução exibirá uma mensagem "Aguardando...". Abra um dos arquivos TypeScript, adicione um espaço e salve o arquivo. Isso disparará a tarefa de inspeção e disparará as outras tarefas a serem executadas na ordem. A captura de tela abaixo mostra uma execução de amostra.

Executando saída de tarefas

Associação a eventos do Visual Studio

A menos que você deseje iniciar manualmente suas tarefas sempre que trabalhar no Visual Studio, associe tarefas a eventos Antes de Compilar, Após Compilar, Limpar e Abrir Projeto.

Associe watch para que ele seja executado sempre que o Visual Studio for aberto. No Explorer do Executor de Tarefas, clique com o botão direito do mouse na tarefa de inspeção e selecione Associações>Projeto Aberto no menu de contexto.

associar uma tarefa à abertura do projeto

Descarregue e recarregue o projeto. Quando o projeto é carregado novamente, a tarefa de inspeção começa a ser executada automaticamente.

Resumo

O Grunt é um executor de tarefas poderoso que pode ser usado para automatizar a maioria das tarefas de compilação do cliente. O Grunt aproveita o NPM para entregar seus pacotes e recursos de integração de ferramentas com o Visual Studio. O Explorer do Executor de Tarefas do Visual Studio detecta alterações nos arquivos de configuração e fornece uma interface conveniente para executar tarefas, exibir tarefas em execução e associar tarefas a eventos do Visual Studio.