Grunt és un task runner de JavaScript, una eina utilitzada per realitzar automàticament tasques freqüents com minificació, compilació, proves unitàries i linting.
Utilitza una interfície de línia d’ordres per executar tasques personalitzades definides en un arxiu (conegut com Gruntfile). Grunt es distribueix a través de NPM i compta amb multitud de complements disponibles.
Abans de començar, convé actualitzar NPM (Llibreria de programari, instal·lador i gestor de paquets), amb el comand:
npm update -g npm
Instal·lem el CLI (Command Line Interface) de grunt de forma global:
npm install -g grunt-cli
Ens desplacem a la carpeta del projecte (p.e. cd [nom-del-projecte]), des done preparem el projecte Grunt, creant el fitxer package.json, mitjançant la ordre:
npm init -y
Després instal·lem Grunt, generant les dependències:
npm install grunt --save-dev
En aquest punt, podem instal·lar els complements (tasques) que volem utilitzar en el nostre projecte, podem instal·lar les següents, dependent quines tasques volem utilitzar:
- Eliminar fitxers i carpetes:
npm install grunt-contrib-clean –save-dev - Concatenar fitxers:
npm install grunt-contrib-concat –save-dev - Comprimir fitxers CSS:
npm install grunt-contrib-cssmin –save-dev - Compilació fitxers Sass a CSS:
npm install grunt-contrib-Sass –save-dev - Minificar fitxers JavaScript:
npm install grunt-contrib-uglify –save-dev - Executar tasques predeterminades quan s’afegeixen, modifiquen o eliminen determinats fitxers:
npm install grunt-contrib-watch –save-dev - Minificar imatges de format PNG, JPEG, GIF i SVG:
npm install grunt-contrib-imagemin –save-dev - Validar fitxers amb JSHint:
npm install grunt-contrib-jshint –save-dev - Copia fitxers:
npm install grunt-contrib-copy –save-dev - Prefixar fitxers CSS:
npm install grunt-autoprefixer –save-dev - Transferir fitxers usant FTP:
npm install grunt-ftp-push –save-dev - Sincronitzar l’explorador:
npm install grunt-browser-sync –save-dev
Ara queda definir en el fitxer Gruntfile.js les tasques concretes. En aquest fitxer tenim per una banda les tasques (grunt.initConfig), la càrrega dels complements (grunt.loadNPMTasks) i el registre de tasques (grunt.registerTask).
module.exports = function(grunt) {
grunt.initConfig({
sass: {
dev: {
files: {
'src/style.css': 'src/sass/style.scss'
}
},
dist: {
options: {
style: 'compressed',
sourcemap: 'none'
},
files: [{
expand: true,
cwd: 'src/sass',
src: ['.scss'],
dest: 'src',
ext: '.css'
}]
}
},
autoprefixer: {
options: {
browsers: ['last 2 version','ie 10'],
grid: true
},
dist: {
files: [{
expand: true,
cwd: 'src',
src: 'style.css',
dest: 'src',
ext: '.pre.css'
}]
}
},
cssmin: {
dist: {
src: 'src/style.pre.css',
dest: 'dist/style.css'
}
},
clean: {
dist: {
src: ['dist/']
},
uploads: {
src: ['dist-uploads/']
}
},
concat: {
options: {
separator: ';',
},
js: {
src: ['src/js/.js','!src/js/built.js'],
dest: 'src/js/built.js'
}
},
uglify: {
dist: {
files: [{
expand: true,
cwd: 'src/',
src: 'js/.js',
dest: 'dist/',
}]
}
},
imagemin: {
dist: {
files: [{
expand: true,
cwd: 'src/',
src: ['/.{png,jpg,gif,svg}'],
dest: 'dist/'
}]
},
uploads: {
files: [{
expand: true,
cwd: 'uploads/',
src: ['/.{png,jpg,gif,svg}'],
dest: 'dist-uploads/'
}]
}
},
copy: {
dist: {
expand: true,
cwd: 'src/',
src: ['/.php'],
dest: 'dist/'
},
style: {
expand: true,
cwd: 'src/',
src: ['style.css'],
dest: 'dist/'
},
localhost: {
expand: true,
cwd: 'dist/',
src: ['/'],
dest: 'c:/xampp/htdocs/wordpress/wp-content/themes/proyecto/'
}
},
ftp_push: {
options: {
host: 'ftp.proyecto.com',
username: 'user',
password: 'pass',
dest: 'proyecto',
},
dist: {
files: [{
expand: true,
cwd: 'dist/',
src: ['/'],
dest:'wp-content/themes/proyecto/'
}]
},
uploads: {
files: [{
expand: true,
cwd: 'dist-uploads/',
src: ['/'],
dest:'wp-content/uploads/'
}]
}
},
browserSync: {
dev: {
bsFiles: {
src : ['c:/xampp/htdocs/wordpress/wp-content/themes/proyecto//']
},
options: {
watchTask: true,
proxy: 'localhost/proyecto',
}
}
},
jshint: {
dev: ['src/js/.js']
},
watch: {
options: {
livereload: true
},
sass: {
files: ['src/sass/style.scss'],
tasks: ['sass:dev']
},
diststyle: {
files: ['src/style.css'],
tasks: ['clean:dist','copy:style','copy:localhost']
},
js: {
files: ['src/js/.js'],
tasks: ['jshint:dev']
}
},
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-imagemin');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-browser-sync');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-ftp-push');
grunt.loadNpmTasks('grunt-autoprefixer');
grunt.registerTask('default',['browserSync:dev','watch:sass','watch:diststyle']);
grunt.registerTask('distribute',[
'clean:dist',
'autoprefixer:dist',
'cssmin:dist',
'uglify:dist',
'imagemin:dist',
'copy:dist'
]);
grunt.registerTask('pushweb',['ftp_push:dist']);
grunt.registerTask('pushuploads',['clean:uploads','imagemin:uploads','ftp_push:uploads']);
grunt.registerTask('pushlocal', ['copy:localhost']);
};
Per executar una tasca (p.e., distribute):
grunt distribute
En aquest cas, aquesta tasca realitza el següent:
- Elimina els fitxers de la carpeta dist.
- Autoprefija el fitxer CSS style.css de la carpeta src, generant el fitxer style.pre.css.
- Minimitza el fitxer style.pre.css, generant el fitxer style.css a la carpeta dist.
- Minimitza els arxius js de la carpeta src/js a la carpeta dist/js.
- Minimitza els arxius d’imatge de formats png, jpg, gif i svg de la carpeta src i les seves subcarpetes de la carpeta dist.
- Copia els fitxers de la carpeta dist a la carpeta del nostre projecte c:/xampp/htdocs/wordpress/wp-content/themes/projecte /.
Si executem grunt, es carreguen les tasques per defecte (default), que en aquest cas carrega el sincronitzador de l’explorador i l’observador (watch), que compila els fitxers Sass a CSS.
Si volem executar una tasca concreta, per exemple, pujar el nostre projecte local al nostre servidor web (p.e., ftp.proyecto.com), executem:
grunt pushweb
Si volem que la tasca de compilació es faci sempre que s’observen canvis en els fitxers Sass, executem la ordre:
grunt watch:sass
en el qual hem indicat la tasca i el seu target específic a executar.
Si volem buidar la carpeta dist-uploads:
grunt clean:uploads
Si volem minimitzar les imatges de la carpeta uploads i passar-les a la carpeta dist-uploads:
grunt imagemin:uploads
Modificant el fitxer Gruntfile.js podem generar noves tasques, redefinir i adaptar-les al nostre projecte en concret, de manera que automatitzar tasques repetitives que realitzem durant el desenvolupament del projecte, estalviant temps i millorant la productivitat.