Ingruz's Blog

Primi passi con Gulp.js

October 09, 2014

Nel moderno panorama dello sviluppo di applicazioni e siti web è importante utilizzare tools che ci aiutino ad automatizzare le operazioni più ricorrenti e tediose, come per esempio la minificazione di files css e javascript, la loro concatenazione, l’ottimizzazione delle immagini etc.

Uno degli ultimi strumenti venuti alla ribalta in questa categoria è Gulpjs. Gulp si appoggia a Nodejs, una piattaforma basata sul runtime javascript di Chrome (V8) che ci permette di utilizzare il linguaggio anche al di fuori di un web browser.

Uno dei principali vantaggi di Gulp rispetto ad altri tool simili, come il più utilizzato Gruntjs (sempre per rimanere in ambiente Node), è il fatto di utilizzare gli streams per gestire il flusso dei files su cui effettuare le operazioni, garantendo una maggiore velocità e flessibilità (ad esempio non sarà necessario scrivere dei files temporanei durante le elaborazioni richieste).

State tranquilli comunque, per utilizzare Gulp non sono richieste grandi conoscenze di Node o della sua architettura! Se non lo state già utilizzando installarlo è comunque molto semplice, basta scaricare l’installer dal sito web ufficiale e seguire le istruzioni relative al vostro sistema operativo.

Installazione

Una volta installato Node si potrà utilizzare il sistema di gestione dei pacchetti integrato, NPM, in modo da installare Gulp sul vostro sistema (utilizzando il flag global) in modo da porterlo usare da riga di comando:

$ npm install --g gulp

Dopodichè posizionatevi nella cartella principale del vostro progetto e installate gulp localmente (tra le dipendenze di sviluppo grazie al flag —save-dev), sempre tramite NPM:

$ npm install gulp --save-dev

Per poter utilizzare Gulp l’ultimo passo necessario è creare un file (sempre nella cartella principale del progetto) dove saranno collocati i vari task da eseguire, con il nome di gulpfile.js.

Inoltre, per futura referenza, supponiamo che la cartella del nostro progetto abbia una struttura simile:

  • dev

    • scripts
    • styles
    • images
  • html

    • scripts
    • styles
    • images

Un primo semplice task

Ora immaginiamo di voler creare un task che ci permetta di ottimizzare le immagini presenti nella cartella images per la pubblicazione sul web.

Per fare questo installiamo il primo plug-in di questo tutorial, sempre utilizzando il fido NPM:

$ npm install gulp-imagemin --save-dev

Ora siamo finalmente pronti per iniziare a scrivere del vero codice! :)

Apriamo il nostro gulpfile.js e inseriamo:

var gulp = require('gulp');
var imagemin = require('gulp-imagemin');

gulp.task('images', function() {
	return gulp.src('dev/images/*')
    .pipe(imagemin())
    .pipe(gulp.dest('html/images'));
});

Vediamo ora di analizzare nel dettaglio quello che abbiamo appena scritto.

  1. abbiamo incluso nello script gulp e il plugin gulp-imagemin tramite la funzione require (tipica dei moduli CommonJS utilizzati da Node);
  2. abbiamo creato un task chiamato images che:

    • prende tutti i files presenti nella cartella dev/images e li fa passare (pipe) attraverso le operazioni successive, in questo caso solamente l’ottimizzazione delle immagini attraverso la chiamata al plugin imagemin()
    • salva il risultato elaborato nella cartella html/images attravero il metodo gulp.dest

Il return all’interno della funzione non è strettamente necessario ma permette ad altre operazioni che dovessero dipendere da questo task di sapere quando è terminato per poter così continuare ad eseguire operazioni sullo stream di files ritornato.

Lanciando il comando gulp images da riga di comando otterremo il seguente output:

[gulp] Using gulpfile C:\blog\gulpfile.js
[gulp] Starting 'images'...
[21:55:37] gulp-imagemin: Minified 2 images (saved 53.8 kB - 1.4%)
[gulp] Finished 'images' after 38 s

Prossimi passi

Vediamo ora di creare un paio di tasks un po’ più complicati in modo da mettere in mostra alcuni dei punti di forza di Gulp, come ad esempio la facilità di concatenare più operazioni sullo stesso flusso di dati.

Per procedere dobbiamo installare altri plugins, con la stessa modalità già vista in precedenza:

$ npm install gulp-uglify --save-dev
$ npm install gulp-concat --save-dev
$ npm install gulp-strip-debug --save-dev
$ npm install gulp-size --save-dev

Ora aggiungiamo un nuovo task al nostro gulpfile.js:

var uglify = require('gulp-uglify');
var concat = require('gulp-concat');
var stripDebug = require('gulp-strip-debug');
var size = require('gulp-size');

gulp.task('scripts', function() {
	gulp.src('dev/scripts/**/*.js')
	    .pipe(stripDebug())
	    .pipe(concat('main.js'))
	    .pipe(uglify())
	    .pipe(size())
	    .pipe(gulp.dest('html/scripts'));
});

Come nell’esempio precedente importiamo i moduli necessari tramite require e poi dichiariamo un nuovo task, scripts.

Questo task prende il contenuto di tutti i files javascript presenti nella cartella dev/scripts (e relative sottocartelle) e li elabora attraverso i plugins:

  1. strip-debug si occupa di eliminare tutte le chiamate a console, alert etc. dal codice;
  2. concat concatena tutti i files in uno unico, main.js;
  3. uglify minifica il file così ottenuto tramite la libreria UglifyJS;
  4. size stampa in console il peso totale in byte del file o dei files.

Infine il risultato viene scritto nella cartella html/scripts, questo sarà l’output che otteremo in console digitando il comando gulp scripts:

[gulp] Using gulpfile C:\blog\gulpfile.js
[gulp] Starting 'scripts'...
[gulp] Finished 'scripts' after 7.2 ms
[00:04:10] all files 84.11 kB

Occupiamoci ora del CSS, prima di tutto installiamo le seguenti dipendenze:

$ npm install gulp-csso --save-dev
$ npm install gulp-autoprefixer --save-dev

Aggiungiamo il task dedicato all’interno del nostro gulpfile.js:

var csso = require('gulp-csso');
var autoprefix = require('gulp-autoprefixer');

gulp.task('styles', function() {
	gulp.src('dev/styles/**/*.css')
	    .pipe(autoprefix())
	    .pipe(concat('main.css'))
	    .pipe(csso())
	    .pipe(size())
	    .pipe(gulp.dest('html/styles'));
});

In questa serie di operazioni ritroviamo alcuni plugins già utilizzati (concat e size) e un paio di volti nuovi:

  1. autoprefixer analizza il codice CSS e aggiunge automaticamente i vendor-prefixes (dove necessari) per quelle funzioni CSS che ancora non sono state implementate in tutti i browser con la sintassi standard (come ad esempio transforms);
  2. csso si occupa invece di minificare i files CSS, similmente a quello che uglifyjs fà per i files javascript.

Tocchi finali

Passando come secondo parametro alla funzione gulp.task un array contenente il nome di altri tasks questi verranno eseguiti prima del corpo del task stesso, in pratica come se fossero delle dipendenze. Inoltre, denominando il task default, questo potrà essere invocato da riga di comando semplicemente con il comando gulp.

gulp.task('default', ['images', 'scripts', 'styles'], function() {
	console.log('All done!');
});

Tuttavia non è molto pratico dover digitare sempre il comando da console ogni volta che si effettua una modifica su un file javascript o css! Per ovviare a questo problema è possibile utilizzare un’altra funzionalità di Gulp, ovvero definire dei watchers:

gulp.task('default', ['images', 'scripts', 'styles'], function() {
	gulp.watch('dev/scripts/**/*.js', ['scripts']);
    gulp.watch('dev/styles/**/*.css', ['styles']);
});

La funzione gulp.watch permette di “osservare” determinati files ed eseguire automaticamente una serie di tasks (definiti nel secondo parametro) quando uno di questi viene modificato: possiamo così lanciare il comando una sola volta all’inizio della sessione e poi continuare a programmare senza preoccupazioni!

Conclusione

In definitiva con poche righe di codice abbiamo creato una serie di tasks che con un semplice comando ci permettono di:

  • ottimizzare le immagini per la pubblicazione sul web;
  • concatenare, minificare e rimuovere le chiamate di debug dai files javascript;
  • concatenare, minificare e aggiungere i vendor prefix necessari nei files css;
  • effettuare queste operazioni automaticamente quando un file viene modificato.

In questo articolo abbiamo solo mostrato la punta dell’iceberg delle capacità e delle operazioni che si possono automatizzare con Gulp. Vi basta dare un’occhiata al numero di plugins attualmente disponibili (quasi 800 ad oggi) per capire che le possibilità sono molteplici.

Nota dell’autore

Questo è il primo articolo scritto per questo blog. A dire il vero non scrivevo un testo così lungo da diversi anni, mi rendo conto quindi che il pezzo presenti diverse lacune grammaticali, stilistiche e di organizzazione dei contenuti. E’ mia intenzione comunque continuare a scrivere con continuità, quindi spero di poter migliorare con il tempo! :)

Nel frattempo qualsiasi critica, suggerimento o commento sono ovviamente i benvenuti!


Emanuele Ingrosso, sviluppatore web full-stack dal 2011, appassionato di videogames, Lego e libri fantasy. Seguimi su Twitter