Ressources en ligne pour apprendre à maîtriser Gulp
Un peu de lecture au format PDF
A Gulp Workflow for Frontend Development Automation
Link
What does our Gulpfile do?
So what exactly does our Gulp frontend workflow automation do for us? Here’s a rundown:
- Handles our CSS
- Compiles all of our SCSS down to CSS, using a cache to make it faster
- Auto-prefixes our CSS for the browsers we support
- Creates SourceMaps for our CSS to make debugging easy
- Pulls in CSS from any third-party modules/packages we use
- Combines and minifies all of our CSS
- Handles our JavaScript
- Transpiles all of the JavaScript we write from ES6 to something web browsers support
- Pulls in JavaScripts from any third-party modules/packages we use
- Uglifies our JavaScripts
- Pulls in any JavaScripts we need to inline in our HTML separately
- Handles live reloading
- CSS/SCSS changes cause an immediate browser repaint without a page load
- JavaScript changes cause the browser to reload the page
- Changes to our Twig/HTML templates cause the browser to reload the page
- Generates CriticalCSS for our website
- Runs an accessibility audit on our website
- Generates a custom icon font using only the glyphs we use via Fontello
- Generates all of the various favicons for our website (and the HTML code for them) from a single source image
- Losslessly minimizes all of the the images our website uses via imagemin
…and a bit more too! But that’s a quick overview of what a workflow automation can do for you. And it’s portable from project to project, because of separation of concerns that puts the data into our package.json.
Gulp 4
Débuter avec Gulp
Les plug-ins Gulp utiles
Astuces d’utilisation de Gulp
Installer Gulp en tant que package Bower
bower install gulp --save-dev
Installer un plugin Gulp non répertorié en tant que package Bower
bower install <url_git://_du_plugin> --save-dev
suivi de sudo npm install <nom_du_plugin> -g
. Exemple :
|
$ bower install git://github.com/terinjokes/gulp-uglify.git --save-dev |
Copier uniquement des fichiers (et pas un chemin complet) dans un dossier
Exemple : j’ai des webfonts accessibles depuis src/webfonts/MyFontsWebfontsKit/webfonts/ et je souhaite les copier via Gulp vers image/webfonts/ sans conserver l’arborescence initiale.
Utiliser le plugin gulp-flatten.
|
var flatten = require('gulp-flatten'); gulp.task('webfonts', function(){ return gulp.src('src/webfonts/**/*.+(eot|svg|ttf|woff|woff2)') .pipe(flatten()) .pipe(gulp.dest('image/webfonts')) }); gulp.task('watch', ['webfonts'], function(){ gulp.watch('src/webfonts/**/*.+(eot|svg|ttf|woff|woff2)', ['webfonts']); }); |
Afficher des logs d’erreurs quand la compilation SASS est foireuse
|
gulp.task('sass', function(){ return gulp.src('src/sass/**/*.scss') .pipe(sass().on('error', sass.logError)) .pipe(gulp.dest('style')) }); |
Logger les erreurs de compilation pour n’importe quel plugin
Ajouter la ligne .pipe(uglify()).on('error', function(e){console.log(e);})
. Exemple d’intégration avec gulp-uglify :
|
gulp.task('uglify', function(){ return gulp.src('src/tmp/*.js') .pipe(uglify()).on('error', function(e){ console.log(e); }) .pipe(cache(flatten())) .pipe(gulp.dest('js')) }); |
Définir un ordre dans lequel les fichiers doivent être chargés
Il peut-être est important que certains fichiers JS soient chargés avant d’autres dans un projet donnée sous peine d’avoir une exception JS au chargement de la page.
Il faut donc dire à Gulp l’ordre dans lequel les fichiers doivent être chargés. Pour cela nous allons utiliser un tableau pour déclarer nos fichiers au lieu d’une regex :
|
var paths = { dist : './dist', scripts : [ './js/common-vars.js', './js/mobile-nav/file.js', './js/carousel/other-file.js', './js/infinite-scroll/other-file.js' ], styles : './styles/**/*.less', html : './**/*.html', images : ['./assets/favicon.ico', './assets/images/**/*.*'] }; |
Mettre en place des tâches de cleaning
Nous allons rajouter les tâches de « cleaning » qui serviront à supprimer du dossier contenant les fichiers destinés à la prod certains fichiers avant l’exécution des tâches :
|
gulp.task('clean:scripts', function (cb) { del(paths.dist + '/js', cb); }); gulp.task('clean:styles', function (cb) { del(paths.dist + '/css', cb); }); gulp.task('clean:images', function (cb) { del(paths.dist + '/images', cb); }); gulp.task('clean:html', function (cb) { del(paths.dist + '/**/*.html', cb); }); |
Maîtriser l’ordre dans lequel les tâches Gulp sont exécutées avec gulp.parallel et gulp.series
Solution ultime: Plug-in run-sequence.
To watch and run a single task upon a change, you will use the following syntax:
|
gulp.task('watch', function() { gulp.watch('app/css/*.css', 'styles'); gulp.watch('app/js/*.js', 'scripts'); gulp.watch('app/img/*', 'images'); }); |
If your project requires you to run multiple tasks upon a change, you will use one of the following syntaxes:
|
gulp.watch('app/css/*.css', gulp.parallel('firstTask', 'secondTask')); gulp.watch('app/js/*.js', gulp.series('thirdTask', 'fourthTask')); |
Simply replace the task string with the method that you need to use for your project and then pass in all tasks that need to be ran as arguments.
Source : How to run Gulp tasks synchronously/one after the other.
Dans un snippet comme celui-ci :
|
gulp.task "coffee", -> gulp.src("src/server/**/*.coffee") .pipe(coffee {bare: true}).on("error",gutil.log) .pipe(gulp.dest "bin") gulp.task "clean",-> gulp.src("bin", {read:false}) .pipe clean force:true gulp.task 'develop',['clean','coffee'], -> console.log "run something else" |
Dans la tâche develop
, je veux d’abord exécuter clean
et, après seulement, exécuter coffee
.
La solution à ce problème est détaillée dans la documentation de Gulp :
|
var gulp = require('gulp'); // takes in a callback so the engine knows when it'll be done gulp.task('clean', function(cb) { // do stuff -- async or otherwise cb(err); // if err is not null and not undefined, the orchestration will stop, and 'coffee' will not run }); // identifies a dependent task must be complete before this one begins gulp.task('coffee', ['clean'], function() { // task 'clean' is done now }); gulp.task('develop', ['clean', 'coffee']); // alternatively: gulp.task('develop', ['coffee']); |
Résolutions d’erreurs liées à l’utilisation de Gulp
Plugin gulp-imagemin – SyntaxError: Use of const in strict mode
Message d’erreur complet lorsqu’on lance Gulp et que le script utilise le plugin gulp-imagemin:
|
/usr/lib/node_modules/gulp-imagemin/index.js:2 const path = require('path'); ^^^^^ SyntaxError: Use of const in strict mode. |
Solution ici : Upgrading Node.js to latest version
The module n makes version-management easy:
sudo npm install n -g
sudo n 0.12.2
For the latest stable version:
sudo n stable
Il est possible qu’avec une mise à jour de nodejs, un autre message d’erreur intervienne après lancement de la commande gulp watch
:
|
(node:7287) fs: re-evaluating native module sources is not supported. If you are using the graceful-fs module, please update it to a more recent version. /usr/lib/node_modules/gulp-sass/node_modules/node-sass/lib/index.js:15 throw new Error(errors.missingBinary()); ^ Error: Missing binding /usr/lib/node_modules/gulp-sass/node_modules/node-sass/vendor/linux-x64-48/binding.node Node Sass could not find a binding for your current environment: Linux 64-bit with Node.js 6.x Found bindings for the following environments: - Linux 64-bit with Node 0.10.x This usually happens because your environment has changed since running `npm install`. Run `npm rebuild node-sass` to build the binding for your current environment. |
A ce moment, il ne faut pas tenter de rebuilder ou de ré-installer node-sass, mais de réinstaller gulp-sass :
sudo npm uninstall --save-dev gulp-sass
sudo npm install --save-dev gulp-sass@2
Plugin gulp-imagemin Unhandled rejection Error :
|
Unhandled rejection Error: spawn /usr/lib/node_modules/gulp-imagemin/node_modules/imagemin-gifsicle/node_modules/gifsicle/vendor/gifsicle ENOENT at exports._errnoException (util.js:1007:11) at Process.ChildProcess._handle.onexit (internal/child_process.js:182:32) at onErrorNT (internal/child_process.js:348:16) at _combinedTickCallback (internal/process/next_tick.js:74:11) at process._tickCallback (internal/process/next_tick.js:98:9) |
Solution : I am getting this when running gulp serve #101.
|
sudo npm cache clean gulp-imagemin sudo rm -rf node_modules/gulp-imagemin sudo npm install gulp-imagemin |
Node Sass could not find a binding for your current environment: Linux 64-bit with Node.js 6.x
Contrairement à ce que propose le message d’erreur un peu plus bas (Run <code>npm rebuild node-sass
to build the binding for your current environment.), il ne faut pas tenter de rebuilder ou de ré-installer node-sass, mais de réinstaller gulp-sass :
|
npm uninstall --save-dev gulp-sass npm install --save-dev gulp-sass@2 |
Au lancement d’une ou plusieurs tâches Gulp, des problèmes de droits sur les fichiers de destination interviennent :
Attention : dans mon cas, l’erreur provenait du fait que je confondais les commandes « chmod » et « chown ». Message d’erreur complet :
|
[12:30:29] 'sass' errored after 212 ms [12:30:29] Error: EPERM: operation not permitted, chmod '/home/intlangf/change30/afflelou/themes/responsive/style/print.css' at Error (native) |
Pour vérifier l’owner et les droits du fichier : ls -l <chemin_vers_le_fichier>
. Ce qui donne :
|
-rw-rw-r-- 1 777 intlangf 0 juil. 11 12:30 /home/intlangf/change30/alainflou/themes/responsive/style/print.css |
En remontant jusqu’à la racine du dossier responsive, je me suis rendu compte que tout le dossier ainsi que l’ensemble de ses sous dossiers et fichiers avait pour owner « 777 ». J’avais probablement dû, à un moment donné, essayer de donner un maximum de droits en lecture/écriture à ce dossier ou à un fichier en particulier, mais en tapant la commande « chown » au lieu de « chmod »! L’owner du fichier est donc devenu 777. Cet utilisateur n’existe pas sur ma machine. Il faut donc redonner l’appartenance du dossier ou du fichier incriminé à un utilisateur existant.
sudo chown -R intlangf:intlangf /home/intlangf/change30/alainflou/themes/responsive
pour donner tous les droits à l’owner intlangf sur le dossier responsive et tous ses sous-dossiers (avec « -R »). Résultat :
|
drwxrwsr-x 10 intlangf intlangf 4096 juil. 11 12:28 responsive/ |
Moving NPM packages main files out or bower_components directory
Problem : You’ve got directory bower_components
full of packages downloaded from NPM, and there’s a lot of fluff, tests and examples, those serve an important purpose to the development of the project, but has little value to the end user. Most of those files don’t belong to the end product and should not be included to the project repo. That’s what this post is all about, moving packages main files out or bower_components
.
gulpfile Cédric
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
const gulp = require('gulp'); const sass = require('gulp-sass'); const sourcemaps = require('gulp-sourcemaps'); const postcss = require('gulp-postcss'); const autoprefixer = require('autoprefixer')({ browsers: ['last 5 versions'], cascade: false }); const mqpacker = require('css-mqpacker')({ sort: true }); const cssnano = require('cssnano')({ autoprefixer: false, svgo: false, zindex: false }); const watch = require('gulp-watch'); gulp.task('css', function(){ return gulp.src('./sass/**/*.scss') .pipe(sourcemaps.init()) .pipe(sass().on('error', sass.logError)) .pipe(postcss([autoprefixer,mqpacker,cssnano])) .pipe(sourcemaps.write('../maps')) .pipe(gulp.dest('./css')); }); gulp.task('watch', function(){ watch('sass/**/*.scss', function() { gulp.start('css'); }); }); |
TODO
Compression du sprite png
- Compression des icones svg avec création de la police
- Séparation plug-ins Gulp dans bower.json
- Régler le watch pour que la tâche Gulp se relance après des modifs sur les fichiers à surveiller
- mettre une option comme –watch pour qu’elle tourne en boucle, et par défaut elle rendrait la main