• seguici su feed rss
  • seguici su twitter
  • seguici su linkedin
  • seguici su facebook
  • cerca

SEI GIA' REGISTRATO? EFFETTUA ADESSO IL LOGIN.



ricordami per 365 giorni

HAI DIMENTICATO LA PASSWORD? CLICCA QUI

NON SEI ANCORA REGISTRATO ? CLICCA QUI E REGISTRATI !

Grunt: introduzione, installazione e primo utilizzo

di :: 07 ottobre 2020
Grunt: introduzione, installazione e primo utilizzo

Grunt è un task runner, cioè è un programma in grado di automatizzare uno o più processi, che altrimenti dovrebbero essere eseguiti manualmente, e che aiutano e semplificano la vita dello sviluppo di un sito web lato frontend.

Ad esempio ci consente di minimizzare (o minificare) i file css e javascript, di concatenarli in un unico file, di ottimizzare le immagini, di compilare i file scss. Andremo a creare tanti task quante sono le attività vogliamo eseguire.

Grunt richiede Node.js per essere installato per cui, prima di ogni cosa, dobbiamo installare Node.js. Ti rimando a questo articolo per la sua spiegazione.

Grunt è molto simile a Gulp, un altro task runner di cui abbiamo già trattato. La principale differenze è che Gulp gestisce i processi tramite la RAM (utilizza principalmente il modulo stream di Node.js) e li scrive immediatamente sul file di destinazione, mentre Grunt utilizza principalmente il modulo fs (file system), creando file temporanei mentre esegue le operazioni. Per questo motivo Gulp svolge le operazioni più velocemente.

Installare Grunt

Con Node.js possiamo installare, sia su Linux che su Windows, l'interfaccia da riga di comando di GULP con questo comando

# npm install -g grunt-cli

Il flag "-g" specifica che npm installerà Grunt a livello globale nel nostro sistema, questo ti permetterà di eseguire i comandi grunt in qualunque directory del tuo server o pc.

Per verificare la versione installata

# grunt --version

Questa la nostra versione

grunt-cli v1.3.2

Ora che Grunt è installato possiamo procedere con la creazione di un progetto.

Creazione di un progetto

Creiamo una cartella dove inserire i files del nostro progetto.

Ad esempio, su Linux, ho creato la cartella "/var/www/progettoGrunt"

# mkdir /var/www/progettoGrunt

Accedo alla cartella

# cd /var/www/progettoGrunt

e quando sono dentro digito il comando

# npm init

Questo comando crea un file chiamato "package.json", il quale conterrà tutte le informazioni sul progetto, tra cui le dipendenze, gli script da eseguire, ecc.

A video apparirà una schermata come questa in cui ti verranno richieste una serire di informazioni (come ad es il nome del progetto).... accetta le impostazioni di default e alla fine digita "yes"

This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help init` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (progettogrunt)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to /var/www/progettoGrunt/package.json:

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


Is this OK? (yes) yes

Bene, il file "package.json" è stato creato. Diamogli un'occhiata

# cat package.json
{
  "name": "progettogrunt",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

Adesso possiamo procedere con l'installazione di GRUNT usando il seguente comando

# npm install --save-dev grunt

L'opzione "--save-dev" installerà GRUNT come una dipendenza di sviluppo del progetto invece che globalmente, cioè installerà e inserirà il nome del pacchetto nel file package.json sotto le "devDependencies".

Infatti, se ricontrolloiamo il contenuto del file, adesso vedremo

# cat package.json
{
  "name": "progettogrunt",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "grunt": "^1.3.0"
  }
}

Viene inoltre create una cartella chiamata "node_modules" che conterrà le varie dipendenze del progetto: prova ad aprirlo e vedrai che è molto corposo.

Ora: se devi trasferire il tuo progetto su un altro pc o server, non copiare la cartella "node_modules", sarà infatti sufficiente eseguire il comando "npm init" affinché npm legga il package.json e scarichi in automatico tutte le dipendeze del progetto. Stesso discorso vale se trasferisci il tuo progetto su Github o simili: escludi la cartella "node_modules" attraverso il file ".gitignore"

Struttura di un progetto Grunt

Nella cartella "progettoGrunt" creiamo due nuove cartella

  • la cartella "src": dove andremo ad inserire i file prima di essere "lavorati" con Grunt
  • la cartella "dst": dove andranno a finire i file ottimizzati per il sito, cioè che andranno in produzione

Inoltre creiamo un file chiamato "Gruntfile.js" che conterrà tutte le task del nostro progetto Grunt, cioè tutte le operazioni che vogliamo realizzare. Per adesso crealo vuoto.

In un sistema Linux, entra nella cartella del progettoGrunt e crea directory e file utilizzando questi comandi

# cd /var/www/progettoGrunt
# mkdir src
# mkdir dst
# touch Gruntfile.js

La nostra directory principale adesso conterrà questi elementi

ls -l
total 76
drwxr-xr-x   2 root root     6 Sep 29 10:23 dst
-rw-r--r--   1 root root     0 Sep 29 10:24 Gruntfile.js
drwxr-xr-x 153 root root  4096 Sep 29 10:21 node_modules
-rw-r--r--   1 root root   259 Sep 29 10:21 package.json
-rw-r--r--   1 root root 62939 Sep 29 10:21 package-lock.json
drwxr-xr-x   2 root root     6 Sep 29 10:23 src

Fino ad ora la spiegazione di GRUNT è stata speculare a quella che avevamo fatto per GULP.

Creare una Grunt Task: il Gruntfile.js

Questo file che conterrà tutte le task del nostro progetto Grunt, cioè tutte le operazioni che vogliamo realizzare, come la minimizzazione dei files, l'ottimizzazione delle immagini... e per fare queste attività utilizzeremo dei plugin.

Per il momento tralasciamo i plugin e vediamo come creare un semplice task che nella realtà non ha applicazioni, ma che ci aiuta a capirne la logica.

Ogni task deve avere un nome, nel nostro esempio lo chiamiamo "world".

Apriamo il file "Gruntfile.js" ed al suo interno scriviamo quanto segue

var grunt = require('grunt');

grunt.registerTask('world', 'il mio primo task', function(){
  console.log('hello world');
});

Come prima cosa abbiamo creato una variabile chiamata "grunt" (ma potevi chiamarla come volevi, ad esempio "pippo") ed incluso "grunt" all'interno del file.

Dopodichè abbiamo creato il task che richiede come primo parametro il nome del task ("world"), come secondo una descrizione del task che è opzionale quindi potevamo tralasciarlo, ed infine la funzione che andrà a creare l'output "hello word".

Salviamo il file, e da terminale lanciamo il task con il comando "grunt" seguito dal nome del task da lanciare

# grunt world

L'ouput sarà il seguente:

Running "world" task
hello world

Done.

Creiamo un secondo task, che chiamiamo "hello" che non risponderà con un semplice "hello word" ma con un "hello" seguito dal nostro nome

var grunt = require('grunt');

grunt.registerTask('world', 'il mio primo task', function(){
  console.log('hello world');
});

grunt.registerTask('hello', 'say hello', function(name){
  if(!name || !name.length)
    grunt.warn('devi indicare il tuo nome.');
    console.log('hello ' + name);
});

Lanciamo il secondo task, indicando, dopo il nome del task e separato da ":", anche il valore del parametro "name" che la funzione si aspetta

# grunt hello:giulio

La risposta sarà

Running "hello:giulio" (hello) task
hello giulio

Done.

Se non avessimo indicato il nome, sarebbe apparso il warning "devi indicare il tuo nome", grazie all'instruzione "grunt.warn".

Running "hello" task
Warning: devi indicare il tuo nome. Use --force to continue.

Aborted due to warnings.

Il warning non blocca l'esecuzione dello script e quindi di eventuali istruzioni successive, ma semplicemente mostra un avviso.

Se invece volessimo bloccare l'esecuzione di Grunt con un errore fatale (Fatal Error), al posto di "grunt.warn" dovremmo utilizzare "grunt.fatal".

Se adesso volessimo lanciare entrambi i task, possiamo farlo semplicemente indicando in sequenza i nomi dei task

# grunt word hello:giulio

In alternativa, all'interno del Gruntfile.js, possiamo creare un nuovo task, ad esempio chiamato "default", che a sua volta andrà a richiamare gli altri task tramite un array di nomi di task

var grunt = require('grunt');

grunt.registerTask('world', 'il mio primo task', function(){
  console.log('hello world');
});

grunt.registerTask('hello', 'say hello', function(name){
  if(!name || !name.length)
    grunt.warn('devi indicare il tuo nome.');
    console.log('hello ' + name);
});

grunt.registerTask('default', ['world', 'hello:giulio']);

Adesso ci basterà chiamare il task "default" per lanciare entrambi i task

# grunt default

Oppure semplicemente

# grunt

Il risultato sarà l'esecuzione dei task "world" ed "hello"

Running "world" task
hello world

Running "hello:giulio" (hello) task
hello giulio

Done.

Aumentiamo la complessita dei nostri taks per avvicinarci ad un reale utilizzo di GRUNT.

Abbiamo visto come utilizzare il metodo "grunt.registerTask" per definrie un task.

Adesso vedaimo il metodo "grunt.registerMultiTask" che, a differenza del precedente, richiede l'esistenza di una "grunt.initConfig" cioè un blocco di codice al cui interno è definita la configurazione del task (una configurazione per ogni task).

Vediamo questo esempio in cui creaiamo il task "print"

var grunt = require('grunt');

grunt.initConfig({
  print: {
    target1: ['index.html', 'src/styles.css', 2],
    target2: 'data',
    hello: 'world'
  }
});

grunt.registerMultiTask('print', 'print targets', function() {
  grunt.log.writeln(this.target + ': ' + this.data);
});

Bene, abbiamo così ultimato l'introduzione ai task di Grunt.

I task nella realtà sono più complessi di quelli visti nell'esempio precedente, ci saranno istruzioni che serviranno, ad esempio, a recuperare i file sorgenti da elaborare, ad elaborarli, a salvarli nella cartella di destinazione,.... e dovremmo utilizzare dei plugin per eseguire queste istruzioni.

Possiamo, a grandi linee, indicare una struttura base di codice per un Grunfile.js

module.exports = function(grunt) {

    // configurazione del progetto
    grunt.initConfig({

     });

    // Qui inizializzerai i plugin

    // Qui definirai i task
};

Tutto il codice va inserito all'interno della funzione "wrapper" grunt. Al suo interno troviamo 3 blocchi di codice

  1. Nel metodo "grunt.initConfig" che conterrà la configurazione del progetto e quindi dei task
  2. Nel secondo blocco andremo ad inizializzare i plugin da utilizzare
  3. Nel terzo blocco definiremo i task (come fatto nel nostro precedente esempio)

Adesso vediamo un vero esempio di file, ma non spaventarti, ce ne occuperemo dettagliatamente nel prossimo articolo dove vedremo vari esempi accuratamente commentati.

Questo esempio serve a compilare un file "less" e trasformarmo in un file "css", e necessita di un plugin chiamato "grunt-contrib-less"

La sua documentazione, disponibile su questa url https://github.com/gruntjs/grunt-contrib-less, spiega come utilizzarlo e presenta un esempio di utilizzo simile a quello che adesso andiamo a scrivere.

Il plugin va installato, e per farlo utilizziamo node.js con questa istruzione

npm install grunt-contrib-less  --save-dev

Nel file "package.json", nel blocco delle "devDependencies", verrà automaticamente inserito questo pacchetto (è una dipendenza). Adesso il plugin è utilizzabile.

All'interno del "Gruntfile.js" scriviamo questo codice

module.exports = function(grunt) {

  // project configuration
  grunt.initConfig({

         // proprietà del task "less"
         less: {
	        development: {
	            files: {
	                "result.css": "source.less"
	            }
	        }
	}
  });

  // inizializzo i plugin
  grunt.loadNpmTasks('grunt-contrib-less');

  // definisco i task
  grunt.registerTask('default',  ['less']);
};

All'interno del "grunt.initConfig" abbiamo definito le proprietà del task "less", comprese tra le parentesi graffe, che dovrà compilare un file chiamato "source.less" (localizzato nella root del nostro progetto) e trasformarlo nel file "result.css" (anch'esso localizzato nella root del nostro progetto).

Per includere il plugin abbiamo utlizzato l'istruzione grunt.loadNpmTasks seguita dal nome del pluign grunt-contrib-less

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

Abbiamo infine creato un task "default" che a sua volta eseguirà il task "less"

runt.registerTask('default',  ['less']);

Per lanciare il task "less" possiamo lanciare il task "default" che a sua volta lo eseguirà

# grunt

Esistono moltissimi plugin: a titolo di esempio guarda questi

Uglify: serve a minimizzare i file .js

https://github.com/gruntjs/grunt-contrib-uglify

CSS Minify: serve a minimizzare i file css

https://github.com/jzaefferer/grunt-css

Autoprefixer: aggiunge automaticamente, dove necessari, i prefissi -webkit, -moz ecc… per quelle funzioni CSS che ancora non sono state implementate in tutti i browser con la sintassi standard

https://github.com/nDmitry/grunt-autoprefixer

ImageMin:serve ad ottimizzare le immagini

https://github.com/gruntjs/grunt-contrib-imagemin

Vedremo nel prossimo articolo alcuni esempi pratici relativi alla minimizzazione di file css e js, e alla ottimizzazione di immagini.

Stay tuned!

# cd /var/www/progettoGrunt

Approfondimenti

Potrebbe interessarti

 
 
 
 
pay per script

Hai bisogno di uno script PHP personalizzato, di una particolare configurazione su Linux, di una gestione dei tuoi server Linux, o di una consulenza per il tuo progetto?

x

ATTENZIONE