Bye bye Grunt.js, hello Gulp.js!

No ano passado, um enxurrada de projetos baseados em JavaScript apareceu no mercado. Grande parte disto deve-se ao fato da linguagem não estar restritamente ligada apenas ao ambiente dos navegadores, e sem dúvidas a plataforma do Node.js contribuiu demais para a expansão de todo esse ecossistema.

No balanço da onda, surgiram alternativas para ferramentas tradicionais de build (Maven, Ant e afins) e entre estas a que mais se destacou foi sem dúvidas o Grunt.js – e você pode acompanhar o beabá desse cara num excelente post publicado pelo Sérgio Lopes aqui no blog da Caelum.

O Grunt.js é uma ferramenta fantástica, mas requer do desenvolvedor alguns conhecimentos que nem todo mundo está verdadeiramente por dentro, como por exemplo o perfeito entendimento da sintaxe literal para construção de objetos que é a base da organização do Grunt.

Screen Shot 2014-01-11 at 12.33.56 AM

A idéia do Gulp.js é abstrair esse conhecimento e trabalhar de uma forma mais simplificada, onde você vai precisar conhecer meia dúzia de métodos e ele por trás faz a abstração dos detalhes necessários para a geração do build.

Começando com o Gulp.js

Assim como o Grunt, o Gulp é uma ferramenta de automação de tarefas feita em JavaScript e rodando em cima do Node.js. Como o core da execução é o Node, precisamos começar nossos trabalhos definindo o arquivo de vai gerenciar os módulos gulp que você utilizará no seu projeto. Para isto, você deve criar na raiz do mesmo o arquivo package.json.

A forma mais fácil de fazer isso, é utilizando a seguinte instrução no terminal:

$ npm init

Esse comando questionará o desenvolvedor sobre uma série de detalhes do projeto (nome, versão, descrição, repositório no git, palavras chaves, autor, licença, etc). Você pode fornecer os detalhes ou ir pressionando Enter e deixar que gerenciador faça as definições baseado em algumas sugestões para as chaves indicadas. No final, o gerenciador exibirá uma amostra do JSON que foi definido e solicitará a sua confirmação para gravação do package.json:

{
  "name": "gulpteste",
  "version": "0.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

Ai basta digitar um “yes” e ser feliz!

Instalando os módulos

Essa é uma parte bem simples, pois baseada nas tarefas que você gostaria de automatizar, será necessário instalar os módulos do Gulp. No nosso exemplo, faremos um procedimento simples, de minificação de arquivos em JavaScript utilizando o Uglify. Então além dos módulos que farão o gulp funcionar (gulp e gulp-util), você precisará instalar o módulo da minificação (gulp-uglify) e de quebra instalaremos também um módulo para monitorar alterações nos arquivos .js e rodará a tarefa da minificação (gulp-watch)

$ npm install gulp --save-dev
$ npm install gulp-util --save-dev
$ npm install gulp-uglify --save-dev
$ npm install gulp-watch --save-dev

Note que para cada módulo instalado, utilizamos o parâmetro –save-dev. Isto modificará nosso arquivo package.json adicionando ao mesmo os módulos que a partir de agora são dependências para rodarmos as tarefas do Gulp. Se você for curioso, pode expiar o conteúdo do package.json, ele deve estar assim:

{
  "name": "gulpteste",
  "version": "0.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "gulp": "~3.3.0",
    "gulp-util": "~2.2.9",
    "gulp-uglify": "~0.1.0",
    "gulp-watch": "~0.3.3"
  }
}

A grande vantagem de instalar os módulos desta maneira, é a fácil reinstalação de todas as dependências. Imagine que inadvertidamente alguém apagou a pasta node_modules do seu projeto. Ou mesmo, imagine que você gostaria de compartilhar este projeto com outro desenvolvedor. Não há a mínima necessidade de versionar a pasta node_modules. Basta ter o package.json atualizado e uma única instrução fará que com que tudo volte ao normal. A título de teste, exclua agora sua pasta node_modules… da até uma tristeza né, afinal você terá que reinstalar tudo novamente. A boa notícia é que agora tudo será bem mais fácil, bastando rodar um:

$ npm install

Pronto! Tudo voltou a ordem que estava anteriormente.

Configurando suas tarefas

Para rodar o Gulp.js, você vai precisar configurar as tarefas que serão executadas. A título de exemplo, vamos criar 2 pastas, uma chamada src e outra chamada build, na raiz do projeto.

Dentro da pasta src, vamos criar uma pasta js onde ficarão todos os arquivos originais de desenvolvimento.

Com a automatização, será criada automaticamente uma pasta js dentro de build, com os arquivos js que estão na pasta src, porém estes últimos estarão minificados pelo Uglify. Para essa mágica toda acontecer, vamos criar na raiz o arquivo de configuração das tarefas, o gulpfile.js.

Abra o arquivo e mãos a obra. O primeiro passo é instanciar os módulos que vamos utilizar:

// instanciando módulos
var gulp = require('gulp');
var gutil = require('gulp-util');
var uglify = require('gulp-uglify');
var watch = require('gulp-watch');

A primeira tarefa que vamos definir, é que vai minificar os arquivos da pasta src/js para pasta build/js. Para isto, utilizaremos o método gulp.task(), que recebe 2 parâmetros. O primeiro é o nome da nova tarefa e o segundo uma função callback com os steps que devem ser executados a partir desta:

gulp.task('scripts', function() {
    // corpo da tarefa
});

Para configurar a minificação, precisamos definir 3 ações:

1 – recuperar os arquivos fonte na pasta de origem;
2 – aplicar a minificação (uglify);
3 – colocar o resultado na pasta de destino.

O código ficará assim:

gulp.task('scripts', function() {
    // corpo da tarefa 
    return gulp
            .src(['src/js/**/*.js'])
            .pipe(uglify())
            .pipe(gulp.dest('build/js'));      
});

Pronto! Para rodá-la, podemos ir ao terminal e digitar:

$ gulp scripts

E conferir se os arquivos foram minificados em build/js.

Para deixar a coisa mais legal, vamos configurar a tarefa que vai monitorar alterações na pasta src/js e rodar a tarefa ‘scripts’, responsável pela minificação. Começamos da mesma forma:

gulp.task('watch', function() {
   // corpo da tarefa 
});

Dentro da nova task, vamos utilizar o método gulp.watch() que recebe 2 parâmetros. No primeiro, definimos a pasta onde estão os nossos arquivos fonte e um função callback que será executada toda vez que um desses arquivos for modificado:

gulp.task('watch', function() {
    // corpo da tarefa 
    gulp.watch('src/js/**/*.js', function(event) {});
});

Agora no callback, o método gutil.log() exibirá informações do arquivo alterado, e através do método gulp.run() definimos qual tarefa será executada. Isso acontecerá toda vez que um arquivo presente em src/js for alterado:

gulp.task('watch', function() {
    // corpo da tarefa 
    gulp.watch('src/js/**/*.js', function(event) {
        gutil.log('File '+event.path+' was '+event.type+', running tasks...');
        gulp.run('scripts');
    });
});

Vamos conferir, no terminal execute:

$ gulp watch

Ai basta alterar qualquer arquivo .js da pasta fonte e ver o resultado na pasta build/js.

Indo além

Agora que temos uma boa noção como tudo funciona, basta repetir o ciclo. Para cada nova tarefa que for automatizar, siga estes passos:

1 – instale o novo módulo usando npm install;
2 – instancie o novo módulo no gulpfile.js;
3 – defina a nova task e o que a mesma executará;
4 – teste e divirta-se!

Conheça mais sobre o projeto, visitando o site oficial. Dê uma olhada no link plugins , lá você vai descobrir uma série de módulos para utilizar com o Gulp.js

Se você quiser saber mais sobre o processo de automatização de tarefas de front-end (utilizando Grunt.js), não deixe deixe de conhecer nosso treinamento de Programação JavaScript . Te vejo por lá!

24 Comentários

  1. Paolo 14/01/2014 at 13:38 #

    Muito bom Léo!
    Havia visto já nas comunidades mas não tirei um tempinho ainda pra ver a fundo, farei isso 😉
    Parabéns pelo post, Abs.

  2. Ney 14/01/2014 at 14:23 #

    Boa!
    Gosto muito do grunt-js, mas vou dar uma olhada no Gulp e testa-lo para ver se adoto nos meus projetos. 😀

  3. Leonardo Souza 14/01/2014 at 14:50 #

    Valeu Paolo, testa sim, é bem legal!

  4. Leonardo Souza 15/01/2014 at 09:58 #

    Eu também confesso meu apreço pelo Grunt, mais vale dar uma olhada no Gulp por sua simplicidade… Afinal meu caro, menos as vezes é mais!

  5. Elias Faiçal 20/01/2014 at 10:49 #

    Muito bom! com certeza vou testar.

  6. Pablo 20/01/2014 at 12:20 #

    Pelo titulo do Post passa uma impressão de que o Grunt vai morrer e vai ser substituido pelo Gulp, mas não será assim, os dois vão continuar sendo usados, porém de acordo a necessidade do projeto será usado um dos dois, muitos developers tem comentado sobre isto ultimamente, veja neste post http://blog.ponyfoo.com/2014/01/09/gulp-grunt-whatever

  7. Marcos César 30/01/2014 at 00:27 #

    Testamos o gulp na empresa onde trabalho, e logo em seguida substituímos o grunt por ele. Ele dá um banho em performance do grunt, fantasticamente mais rápido, utilizamos pra compilar os arquivos less do bootstrap, dar refresh pelo chrome (live reload), concatenar os js… tudo em questão de poucos mili segundos, ou nano segundos dependendo do caso, dando refresh instantâneo… Fantástico, pratico, fácil e rápido. Vale a pena.

  8. Leonardo Souza 30/01/2014 at 00:45 #

    Excelente observação Marcos César, eu também percebi nos meus testes que o gulp performou melhor em algumas tasks que eu já estava rodando como grunt. Por isso repito, vale a pena dar uma olhada pra ele com atenção.

  9. Tiago 11/04/2014 at 11:54 #

    Leonardo, gostei do seu artigo, mas acho que vc deveria falar um pouco mais das diferenças conceituais entre o grunt e o gulp (principalmente na questão da manipulação de streams), para isso, recomendo muito o podcast http://javascriptjabber.com/097-jsj-gulp-js-with-eric-schoffstall/. Esse podcast é uma entrevista com Eric Schoffstall que é o criador do gulp.

  10. Cezar Luiz 13/05/2014 at 16:00 #

    Oi Leonardo, tudo bem? Excelente post, estava me matando no Grunt e o Gulp é de longe o mais fácil! (minha opinião).

    Só uma observação, você poderia atualizar seu post pois estou recebendo essa mensagem do gulp “gulp.run() has been deprecated. Use task dependencies or gulp.watch task triggering instead.”.

    Obrigado!

  11. Tiago Celestino 15/05/2014 at 15:10 #

    Acho que a facilidade vem do uso, independente da sintaxe. Uso bastante o grunt e já li muito sobre o gulp, mas ainda não vi nenhuma beneficio direto. Vão falar da performance, mas nesse ponto eu vejo que o desenvolvedor precisa saber usar de “forma correta” o que o task manager tem a oferecer.

    Uso grunt para grandes projetos e nunca tive problemas de performance.

  12. Rômulo 21/05/2014 at 21:40 #

    Curti muito sei artigo. Parabéns.

  13. Nilton 29/05/2014 at 00:03 #

    Ótimo post! Direto e simples porém comentando cada etapa do processo sem perder o foco.
    Porém devo fazer uma observação: antes do “npm install gulp –save-dev” é preciso dar um “npm install -g gulp” para que o comando “gulp” funcione na linha de comando”, já que “g” o instala globalmente (e só é preciso fazer uma vez) enquanto o segundo o adiciona a node_modules/ e uma entrada no package.json, ou seja, localmente.

  14. Diego 29/05/2014 at 20:53 #

    Muito bom! Testei e realmente é muito mais rápido e intuitivo. Pouco código e simples visualização.
    Parabéns!!!

  15. Rhamsés Soares 24/08/2014 at 04:13 #

    Muito bom o artigo. Parabéns.

    No youtube, tem uma série de videos que mostram algumas funcionalidades legais do Gulp. Eu que não consegui me adaptar com o Grunt estou achando um máximo.

    http://bit.ly/1p4pUBt

  16. Willian 13/05/2015 at 23:49 #

    Cara se eu (uso win) localizo a minha pasta do projeto e faço todas essas intalações na pasta e talz, ai quando eu criar outro projeto preciso instala tudo de novo?
    E como faço para minificar todos os arquivos, além do js, tenho que ter uma task para cada uma? E com o watch consigo assistir o html e css também?

  17. Arlei 24/05/2015 at 11:16 #

    Excelente artigo!

  18. Leonardo Souza 25/05/2015 at 11:19 #

    Então Willian, a sacada é que quando você instalar os módulos isso vai popular o arquivo do manifesto, o package.json. Quando iniciar um projeto novo, ou até mesmo copiá-lo para outra pessoa, você não precisa carregar junto a pasta node_modules (que geralmente é bem pesada). Basta ter este arquivo que mencionei na raiz do seu projeto, e pelo terminal rodar um npm install.

  19. Henrique Silvério 10/08/2015 at 09:22 #

    “O Grunt.js é uma ferramenta fantástica, mais requer do desenvolvedor alguns conhecimentos que nem todo mundo está verdadeiramente por dentro, como por exemplo o perfeito entendimento da sintaxe literal para construção de objetos…”

    Na boa, se o cara não sabe criar um objeto literal, ele deveria antes de tudo estudar a linguagem ao invés de querer automatizar build. xD

    Enfim, gulp é sim interessante, e é sempre bom ter opções. =]

  20. Charles 25/08/2015 at 15:17 #

    Show. Parabens pelo post!

Deixe uma resposta