• 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: come minimizzare file css e javascript, ed ottimizzare le immagini

di :: 08 ottobre 2020
Grunt: come minimizzare file css e javascript, ed ottimizzare le immagini

Grunt è un task runner, cioè un programma in grado di automatizzare uno o più processi che altrimenti dovrebbero essere eseguiti manualmente.

Ci siamo occupati di introdurre Grunt e di come installarlo, quindi ripartiamo dall'articolo precedente... e se non lo avete letto fatelo adesso perchè è la premessa a quanto andremo a spiegare.

Nella cartella del nostro progetto, chiamata "progettoGrunt", oltre ai file e directory creati in fase di creazione del progetto, abbiamo questa architettura:

  • src: directory che contiene i file css, javascript ed immagini sorgenti, che verranno eleborate da Grunt
  • dst: directory che contiene i file destinati alla produzione, cioè elaborati da Grunt
  • test: contiene il codice per testare il progetto (cioè il o i file html che conterranno i file ottenuti dalla elaborazione di Grunt)
  • Gruntile.js: file javascript dove inseriamo i task

Oggi vediamo come creare alcuni task per ottimizzare file css, javascript ed immagini presenti nel nostro progetto web.

I file sorgenti saranno quindi inserira nella directory "src" dove all'interno creiamo 3 cartelle, una destinata ai css, una ai javascript, una alle immagini.

src
   - js
   - css
   - images

Quando si parla di minimizzare o minificare i file css e javascript intendiamo l'operazione che comprime al massimo i file.

Ad esempio prova ad aprire questo file "minificato" di JQuery: come puoi vedere il codice è compatto e ridotto al minimo. Questo significa un peso minore del file.

Il nostro obbiettivo e quello di ottenere lo stesso risultato partendo dai file css, javascript ed immagini del nostro sito.

Ottimizzare i file JAVASCRIPT

Vediamo iniziamlemente come ottimizzare i JAVASCRIPT. L'obiettivo è accorpare tutti i file js in un file unico a cui daremo il nome "all.js", che dovremo anche minificare.

Quindi presupposto è mettere nella cartella "src/js" tutti i javascript che dovranno subire questo "trattamento"

Per fare questo, come prima cosa, dobbiamo installare alcuni plugin, che installeremo a livello del progetto (non a livello globale).

Accediamo alla cartella del progetto

# cd /var/www/progettoGrunt

ed installiamo questi plugin

# npm install grunt-contrib-uglify --save-dev
# npm install grunt-contrib-jshint --save-dev
# npm install grunt-contrib-concat --save-dev
# npm install grunt-contrib-watch --save-dev

Installati i plugin, apriamo il "Gruntfile.js" e scriviamo questo codice

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    concat: {
      options: {
        separator: ';'
      },
      dist: {
        src: ['src/**/*.js'],
        dest: 'dst/<%= pkg.name %>.js'
      }
    },

    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
      },
      dist: {
        files: {
          'dst/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
        }
      }
    },

    jshint: {
      files: ['Gruntfile.js', 'src/**/*.js', 'dst/**/*.js'],
      options: {
        // options here to override JSHint defaults
        globals: {
          jQuery: true,
          console: true,
          module: true,
          document: true
        }
      }
    },

    watch: {
      files: ['<%= jshint.files %>'],
      tasks: ['jshint']
    }
  });

  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-concat');

  grunt.registerTask('default', ['jshint', 'concat', 'uglify']);
};

Analizziamo il codice partendo dal fondo

Abbiamo inizializzato i vari plugin con "grunt.loadNpmTasks"

Abbiamo creato un task "default" che a sua volta esegue in un sol colpo i task "jshint", "concat", "uglify".

Nel "grunt.initConfig" indichiamo le proprietà dei singoli task. Ma prima di questi abbiamo l'istruzione "pkg: grunt.file.readJSON('package.json')," che legge il contenuto del file "package.json" da cui andremo a prelevare alcune informazioni, che scriveremo sul file finale, nel nostro esempio il "name" del progetto.

Analizziamo adesso i singoli task.

Il task jshint: con questo task verifichiamo la presenza di problemi nel codice javascript dei nostri files, l'uso dell'operatore di uguaglianza invece dell'operatore di uguaglianza rigorosa e la definizione di variabili e funzioni non utilizzate.

Diamo in pasto a jshint tutti i file .js presenti nel nostro progetto, presenti sia nella cartella "src" che "dst" che il "Gruntfile.js".

Il task concat: preleva tutti i file presenti nel suo target cioè la direcrory "src", ed eventuali sue sottodirectory, che hanno come estenzione .js, e crea un unico file sotto la cartella "dst" che avrà come nome il "name" del package, prelevato dal file "package.json" ed estensione .js

Questo target ha un nome: "dist" (ma potevamo dargli un nome qualunque). Questo nome verrà richiamato dal task uglify.

Il task uglify: andrà a creare, partendo dal file creato dal task precedente (<%= concat.dist.dest %>), un file minificato che avrà come nome il "name" del package ed estensione ".min.js"

Il task watch: quando viene rilevato che uno dei file javascript dati in pasto a jshint viene modificato, verrà eseguito il task jshint. Tra poco lo vediamo in azione.

Bene, prima di lanciare il task default, proviamo il task jshint

# grunt jshint

Se sono presenti errori nel file verranno evidenziati con in questo esempio e veniamo inviatati a correggerli

Running "jshint:files" (jshint) task

   src/js/contatti.js
     25 |        var lnh = email.length;
                     ^ 'lnh' is already defined.

>> 1 errors in 2 files
Warning: Task "jshint:files" failed. Use --force to continue.

Aborted due to warnings.

Provvediamo alla correzione e rilanciamo il task... adesso il file è corretto.

Running "jshint:files" (jshint) task
>> 2 files lint free.

Done.

Adesso vediamo cosa fa il task watch. che non inseriamo nel task default, cioè non servirà per minimizzare i file, ma ha la sua utilità che adesso vediamo.

# grunt watch

L'output sarà il seguente

Running "watch" task
Waiting...

Il task resta in ascolto....

Non chiudiamo il terminale, e proviamo a modificare uno dei file javascript presenti nella cartella "src" (nel nostro esempio un file chiamato contatti.js) .... non appena fatta la modifica il task watch si sveglierà dal suo stato di attesa e visualizzerà quanto segue

Running "watch" task
Waiting...

>> File "src/js/contatti.js" changed.
Running "jshint:files" (jshint) task
>> 2 files lint free.

Done.
Completed in 0.268s at Wed Sep 30 2020 13:39:59 GMT+0200 (Central European Summer Time) - Waiting...

In poche parole, ha verificato che un file è stato modificato, e l'ha passato al task jshint per la verifica.

Siamo quindi finalmente al lancio del task default, con cui possiamo procedere all'esecuzione di tutti i task

# grunt

Apriamo la cartella "dst" e troveremo il file "all.js" composto dall'unione di tutti i nostri file js, ottimizzati e minificati.

Ottimizzare i file CSS

In aggiunta ai task precedenti, vogliamo concatenare, cioè inserire in un unico file, anche i file css, come abbiamo fatto per i js.

Il task concat in questo momento ha un unico "target" chiamato "dist" cioè un unico obbiettivo: i files js contenuti nella cartella "src"

      dist: {
        src: ['src/**/*.js'],
        dest: 'dst/<%= pkg.name %>.js'
      }

Adesso modifichiamo il task aggiungendo un secondo target, che chiamiamo ad esempio "mycss", che preleva i file css dalla cartella "src" e da questi crea un unico file che avrà come nome il "name" del package

    concat: {
      options: {
        separator: ';'
      },
      dist: {
        src: ['src/**/*.js'],
        dest: 'dst/<%= pkg.name %>.js'
      },
      mycss: {
        src: 'src/**/*.css',
        dest: 'dst/<%= pkg.name %>.css'
      }
    },

Il primo step per ottimizzare i css è completato. Lanciando questo task verrà creato un unico file css.

Adesso dobbiamo minificare questo file css creato dal task concat e per questa funzione utilizziamo il seguente plugin

Entriamo nella cartella del progetto (dovreste già esserci)

# cd /var/www/progettoGrunt

ed installiamo il plugin

# npm install grunt-contrib-cssmin --save-dev

Modifichiamo il "Gruntfile.js" aggiungendo questi plugin

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

Aggiungiamo un task che chiamiamo "cssmin", che prenderà il file ".css" creato dal task concat, e lo minifica creando un file ".min.css"

cssmin: {
	css: {
	      src: 'dst/<%= pkg.name %>.css',
	      dest: 'dst/<%= pkg.name %>.min.css'
	}
}

Il "Grunfile.js" adesso avrà questo codice

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    concat: {
      options: {
        separator: ';'
      },
      dist: {
        src: ['src/**/*.js'],
        dest: 'dst/<%= pkg.name %>.js'
      },
      mycss: {
        src: 'src/**/*.css',
        dest: 'dst/<%= pkg.name %>.css'
      }
    },

    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
      },
      dist: {
        files: {
          'dst/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
        }
      }
    },

    jshint: {
      files: ['Gruntfile.js', 'src/**/*.js', 'dst/**/*.js'],
      options: {
        // options here to override JSHint defaults
        globals: {
          jQuery: true,
          console: true,
          module: true,
          document: true
        }
      }
    },

    watch: {
      files: ['<%= jshint.files %>'],
      tasks: ['jshint']
    },

    cssmin: {
	   css: {
	      src: 'dst/<%= pkg.name %>.css',
	      dest: 'dst/<%= pkg.name %>.min.css'
	   }
    }

  });

  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-cssmin');

  grunt.registerTask('default', ['jshint', 'concat', 'uglify', 'cssmin']);
};

Bene, lanciamo il task default e vediamo il risultato

#grunt

Nella cartella "dst" troveremo il file minificato "progettogrunt.min.css"

Ottimizzare le immagini

L'ultimo esempio che vediamo oggi è l'ottimizzazione delle immagini.

Mettiamo le immagini nella cartella "dst/images".

Utilizziamo il plugin "grunt-contrib-imagemin", che andiamo ad installare così

# npm install grunt-contrib-imagemin --save-dev

Modifichiamo il "Gruntfile.js" aggiungendo questo plugin

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

Aggiungiamo un nuovo task chiamato imagemin che deve prelevare tutti i file della cartella "src/images" (ed eventuali sottocartelle) con estensione "png,jpg,gif" e creare dei file ottimizzati da inserire nella cartella "dst/images"

imagemin: {
            options: {
                optimizationLevel: 3,
                svgoPlugins: [{removeViewBox: false}],
                use: [mozjpeg()] // Example plugin usage
            },

	dynamic: {
	    files: [{
	        expand: true,
	        cwd: 'src/images/',
	        src: ['**/*.{png,jpg,gif}'],
	        dest: 'dst/images'
	    }]
	}
}

Il nuovo task preleva le immagini dalla nostra cartella, le ottimizza, e le pone in una analoga cartella "images" all'interno della cartella "dst" (se non presente la crea)

Questo task utilizza la libreria "imagemin-mozjpeg" per la compressione dei file jpg, per cui procediamo anche alla sua installazione a livello globale visto che potremmo riutilizzarlo

# npm install imagemin

E adesso dobbiamo includerlo nel "Gulfile.js", così:

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

Infine aggiungiamo al task default il nuovo task imagemin

grunt.registerTask('default', ['jshint', 'concat', 'uglify', 'cssmin', 'imagemin']);

Il "Gruntfile.js" adesso sarà così

module.exports = function(grunt) {

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

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    concat: {
      options: {
        separator: ';'
      },
      dist: {
        src: ['src/**/*.js'],
        dest: 'dst/<%= pkg.name %>.js'
      },
      mycss: {
        src: 'src/**/*.css',
        dest: 'dst/<%= pkg.name %>.css'
      }
    },

    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
      },
      dist: {
        files: {
          'dst/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
        }
      }
    },

    jshint: {
      files: ['Gruntfile.js', 'src/**/*.js', 'dst/**/*.js'],
      options: {
        // options here to override JSHint defaults
        globals: {
          jQuery: true,
          console: true,
          module: true,
          document: true
        }
      }
    },

    watch: {
      files: ['<%= jshint.files %>'],
      tasks: ['jshint']
    },

    cssmin: {
	 css: {
	      src: 'dst/<%= pkg.name %>.css',
	      dest: 'dst/<%= pkg.name %>.min.css'
	 }
    }, 

    imagemin: {
            options: {
                optimizationLevel: 3,
                svgoPlugins: [{removeViewBox: false}],
                use: [mozjpeg()] // Example plugin usage
            },

	  dynamic: {
	    files: [{
	        expand: true,
	        cwd: 'src/images/',
	        src: ['**/*.{png,jpg,gif}'],
	        dest: 'dst/images'
	    }]
	  }
    }

  });

  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-imagemin');

  grunt.registerTask('default', ['jshint', 'concat', 'uglify', 'cssmin', 'imagemin']);
};

Bene, adesso lanciamo il task default, oppure semplicemente il task imagemin, a vostra discrezione

# grunt

Dentro la cartella "dst", se non era presente, è stata creata la cartella "images" e dentro troviamo le immagini ottimizzate con un peso ridotto.

Grunt e Gulp

Un altro task runner, molto simile a Grunt, è Gulp a cui abbiamo dedicato già un articolo.

La principale differenza tra i due è 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.

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