Meu site, passo-a-passo-#5 — Funcionamento básico do Gulp — processando Pug
Depois de detalhar como seria a estrutura das pastas do meu projeto, é hora de começar a trabalhar.
Não seria muito melhor que alguém, desde já, pudesse me ajudar com o serviço ‘pesado’: copiar arquivo, upload, compactação, etc?
Além das cópias dos arquivos para a pasta destino, há os dois processos, LESS e PUG, que interpretarão os arquivos fontes e estilos, para convertê-los, respectivamente, para CSS e HTML.
Depois que gerasse os arquivos HTML e CSS, eu teria que copiá-los, junto com os arquivos de imagens, código JavaScript e outros plug-ins, para a pasta de destino. A cada alteração que eu fizesse no sistema, teria que copiar os arquivos novamente.
Imagine este processo em um projeto com mais de 100, 200 arquivos? Dureza, né?
Eu sempre trabalhava deste jeito manual, até conhecer os automatizadores de tarefa, que são exatamente o que você deve estar imaginando: são programas que fazem processos para você: copiar arquivos para uma pasta, apagar arquivos, concatenar código-fonte, etc.
Eles recebem um script, onde você escreve o que deve ser feito, na ordem que devem ser feitas, e quais condições eles devem ser realizadas.
Algo parecido com os automatizadores são o scripts do Windows (os arquivos .bat). Só que os automatizadores levam bastante vantagem dos scripts convencionais, pois já possuem muita coisa pronta, especialmente para projetos de desenvolvimento. Além do fato de que os scripts dos automatizadores podem ser replicados em outras máquinas, independente do sistema operacional ou do servidor.
O automatizador que eu escolhi para este projeto é o Gulp (http://gulpjs.com/). Ele é simples de se utilizar, e já possui uma boa variedade de plug-ins disponíveis (que são as tais ‘rotinas prontas’ que comentei acima. ).
Após a instalação do Gulp, com o NPM (também no meu último post:), eu instalo os plug-ins do Pug e do Less:
npm install gulp-pug –save-dev
npm install gulp-less –save-dev
O arquivo gulpfile.js
O script para execução das tarefas é um programa escrito em JavaScript, com o nome gulpfile.js. Eu crio este arquivo na pasta raiz do meu projeto.
No início, eu faço a instanciação das bibliotecas importadas pelo NPM:
var gulp = require(‘gulp’);
var pug = require(‘gulp-pug’);
var less = require (‘gulp-less’);
Depois, eu crio uma tarefa e salvo o arquivo:
gulp.task (‘tarefa’);
Este é o básico que o gulp precisa para funcionar. Para executar esta tarefa, eu executo na linha de comando: gulp, mais o nome da tarefa. Deste jeito:
gulp tarefa
Pronto, o Gulp executará toda a minha programação dentro de ‘tarefa’. Obviamente, nada vai ser executado, por que não escrevi nada dentro de ‘tarefa’. Portanto, vamos programar toda a nossa automatização dentro da task.
A programação de cada tarefa é feita no segundo parâmetro desta função, que também é uma função (não falei errado, é uma função que recebe como parâmetro uma função. No Javascript, função nada mais são do que um tipo de valor):
gulp.task (‘tarefa’, function(){
});
Esta função retornará o resultado da chamada da função gulp.src, onde você deverá informar o caminho dos arquivos de origem:
gulp.task (‘tarefa’, function(){
return gulp.src(“*.*”);
});
O parametro do arquivo recebe o nome do arquivo, caracteres coringas, como ’*’ ou ’?’, ou um vetordestas duas primeiras opções. Exemplos:
return gulp.src(“index.pug”);
return gulp.src(“*.pug”);
return gulp.src([“index.pug”, “home.pug”]);
Este é o começo da tarefa, onde eu defino a origem dos arquivos a serem lidos pela task. Você pode aprender todas as opções disponíveis, acessando a documentação desta função(em inglês), que descreve a função nobe-glob, que é a base da função ‘src’.
Até aqui, você pode estar pensando em fazer um gulp.src (’*.*’), parar ler todos os arquivos de uma vez. Tenho más notícias: isto não vai funcionar. Por um motivo bem óbvio: o programa vai gerar erro se um processo para PUG ler arquivos .less, e vice versa.
A solução para isto é criar tarefas distintas para cada tipo de arquivo, ou para cada pasta, ou, no geral, para cada pedaço do seu projeto.
Se eu preciso segregar o PUG e o Less em 2 tarefas distintas, é melhor eu renomear esta tarefa. Nela, vou apenas selecionar os arquivos PUG para serem processados, lendo eles dentro da pasta onde eles ficarão. Veja como ficará o comando:
gulp.task (‘tarefa-pug’, function(){
return gulp.src(“views/*.pug”);
});
Depois que o processo selecionar estes arquivos, ele deverá executar o plugin PUG para converte-los para arquivos HTML. Para programar desta maneira, você deverá escrever assim:
gulp.task (‘tarefa-pug’, function(){
return gulp.src(“views/*.pug”).pipe(pug());
});
Explicando o código de uma maneira muito, muito mastigada, pense que o gulp.src carregará todos os arquivos em uma espécie de sequência, uma corrente de arquivos (chamada no Gulp de ’stream’). Quando o Gulp terminar de carregar todos os arquivos, ele executará a função pipe(), que executará a outra função definida dentro dela (que neste caso é a função pug()).
A função é um tipo de promise, que é um recurso no JavaScript que funciona como uma espécie de ‘evento’. Ela só executará quando a instrução anterior à ele for concluída. No contexto do gulp, o pipe() é auto-explicativo. É como ele descrevesse cada etapa de uma tarefa. Veja como eu posso criar estas etapas, neste exemplo:
gulp.src(“*.*”).pipe(funcao()).pipe(funcao()).pipe(funcao()).pipe(funcao())…;
Para explicar melhor os conceitos de Promise, e da função Pipe, seguem abaixo 2 links, com textos bem intuitivos sobre este dois recursos (em inglês):
- https://davidwalsh.name/promises (Promises)
- https://nodejs.org/api/stream.html#stream_readable_pipe_destination_options (Pipe)
A próxima etapa da tarefa é salvar os arquivos que já foram processados pelo PUG. Eu crio uma outra função pipe(), onde eu informo a função gulp.dest(). Está função recebe o caminho de destino de todo o processo e prepara este caminho, para que o gulp salve a corrente de arquivos que ele está operando.
gulp.task (‘tarefa-pug’, function(){
return gulp.src(“views/*.pug”).pipe(pug()).pipe( gulp.dest(‘dist/’));
});
Pronto. O script está finalizado, e eu posso executá-lo via console.
Lembre-se de que você deverá executar o pug com o novo nome da tarefa:
gulp tarefa-pug
No próximo post, uma pausa no desenvolvimento, para começar o design.