Automatiser son flux de travail : compilation SCSS et mise en ligne avec Gulp
Nous avions déjà présenté en 2018 les bases de Gulp dans l’article Prendre en main Gulp.js, ainsi qu’une série complète dédiée à Sass : Comprendre et utiliser Sass. Depuis, les usages ont évolué, les outils aussi, mais les besoins restent les mêmes : gagner du temps, éviter les oublis, simplifier les tâches répétitives.
Dans ce nouvel article, nous allons mettre en place une chaîne automatisée : à chaque sauvegarde d’un fichier .scss
, Gulp le compile, le minifie et le transfère automatiquement sur le serveur. Une manière concrète d’ancrer de bonnes pratiques dans le quotidien, en restant simple, local, et efficace.
Préparer l’environnement de travail
Avant d’écrire une seule ligne de code, nous allons structurer proprement notre dossier de travail. L’idée est de séparer clairement les fichiers sources (dans un dossier scss
, js
, html
, etc.) et les fichiers de production finaux (dans un dossier assets
, par exemple). Cette organisation nous permettra ensuite d’automatiser les tâches sans confusion.
Si vous travaillez sur un lecteur réseau mappé (comme Z:\
, Q:\
ou autre), évitez d’exécuter npm
directement à sa racine. Cela provoque souvent des erreurs, notamment dans la gestion des dépendances et des chemins internes. Il est préférable de créer un sous-dossier dédié à vos projets (Z:\Sites\MonProjet\
) et de lancer l’initialisation à cet endroit précis.

Une fois que nous sommes positionnés sur le bon lecteur, nous pouvons initialiser le projet avec npm
. Cela va créer le fichier package.json
, puis installer les outils nécessaires :
# Création du dossier projet (si besoin) et déplacement
mkdir mon-projet && cd mon-projet
# Initialisation du projet
npm init -y
# Installation des modules nécessaires
npm install --save-dev gulp gulp-sass sass gulp-sourcemaps gulp-clean-css
Chaque module a un rôle spécifique dans notre chaîne d’automatisation. Nous allons les présenter un à un avant d’écrire la première tâche Gulp.
Comprendre les outils installés
Lors de l’installation, nous avons ajouté plusieurs modules essentiels pour automatiser notre flux de travail. Chacun d’eux répond à une étape précise, de la compilation à l’optimisation. Il est utile de comprendre leur rôle avant d’écrire notre premier script.
gulp
est le cœur du système. Il orchestre les différentes tâches que nous allons décrire dans le fichiergulpfile.js
. Sans lui, rien ne s’exécute.gulp-sass
permet de convertir nos fichiers.scss
en.css
. Il fonctionne ici avecsass
, installé séparément, qui fournit le compilateur Dart Sass en local. C’est la version officielle et maintenue de Sass, celle que nous recommandons.gulp-sourcemaps
génère un fichier de correspondance entre le SCSS original et le CSS final. Cela permet, même après minification, de savoir quelle ligne SCSS correspond à chaque ligne CSS, ce qui est très utile en phase de développement.gulp-clean-css
minifie le CSS produit, en supprimant tout ce qui n’est pas nécessaire : espaces, commentaires, lignes inutiles… Le fichier devient plus léger, plus rapide à charger.
Nous verrons plus tard comment ajouter un système de transfert automatique vers un serveur. Pour l’instant, concentrons-nous sur la chaîne locale : compilation, sourcemaps, minification.
Organiser son projet
Nous allons adopter une structure claire, avec un dossier scss/
pour les fichiers sources, et un dossier assets/
pour les fichiers générés. À l’intérieur de assets/
, nous créons un sous-dossier css/
qui recevra les fichiers compilés à partir du SCSS. Cette séparation permet de garder un espace de travail propre et extensible.
Voici la structure de départ :
mon-projet/
├── scss/
│ └── style.scss
├── assets/
│ └── css/
├── gulpfile.js
└── package.json
Lorsqu’un fichier .scss
est modifié, Gulp le compile, le minifie, et place le résultat dans assets/css/
. Par la suite, nous pourrons enrichir le projet avec d’autres traitements similaires pour des fichiers js
, html
, ou même des images, tout en gardant la logique centralisée dans le dossier assets/
.
Mettre en place le fichier gulpfile.js
Le fichier gulpfile.js
décrit toutes les étapes de traitement que Gulp doit enchaîner automatiquement. Dans cette première version, nous allons nous concentrer sur la compilation SCSS en CSS minifié, avec génération de sourcemaps pour faciliter le débogage.
Importer les modules nécessaires
Voici les outils que nous allons utiliser. Ils ont été installés plus tôt via npm
.
const gulp = require('gulp'); // moteur d’automatisation principal
const sass = require('gulp-sass')(require('sass'));// compile SCSS en CSS avec Dart Sass
const sourcemaps = require('gulp-sourcemaps'); // génère des fichiers .map pour le débogage
const cleanCSS = require('gulp-clean-css'); // minifie le CSS final
Nous utilisons ici gulp-sass
en précisant require('sass')
comme moteur de compilation. C’est une pratique courante depuis que le module Dart Sass est séparé.
Définir les chemins sources et destinations
Pour éviter les répétitions dans notre script, nous pouvons déclarer nos chemins en début de fichier. Cela rend le code plus lisible et plus facile à adapter :
// Chemins configurables
const paths = {
scss: {
src: 'scss/**/*.scss', // tous les fichiers .scss du dossier scss/
dest: 'assets/css' // dossier de sortie pour le CSS compilé
}
};
Ici, nous disons que tous les fichiers .scss
du dossier scss/
(et de ses sous-dossiers) doivent être surveillés, et que le résultat sera stocké dans assets/css/
.
Créer la tâche de compilation
Voici la fonction qui assure toute la chaîne de transformation. Cette fonction ne renomme pas le fichier en .min.css
volontairement. Le fichier s’appellera simplement style.css
, mais sera déjà minifié. On peut bien sûr adapter cette convention plus tard si besoin. Chaque étape est commentée :
// Tâche de compilation du SCSS
function compileSCSS() {
return gulp.src(paths.scss.src) // récupère tous les fichiers SCSS définis plus haut
.pipe(sourcemaps.init()) // initialise les sourcemaps pour le suivi du code
.pipe(sass({ outputStyle: 'expanded' }) // compile le SCSS avec une indentation lisible
.on('error', sass.logError)) // capture et affiche les erreurs de compilation
.pipe(cleanCSS({ level: 2 })) // minifie le CSS avec un niveau d’optimisation avancé
.pipe(sourcemaps.write('.')) // écrit les fichiers .map à côté des CSS produits
.pipe(gulp.dest(paths.scss.dest)); // enregistre le CSS final dans assets/css/
}
Depuis plusieurs années, gulp-sass
ne contient plus directement le moteur de compilation Sass. Il agit comme un simple pont vers un compilateur externe. C’est pourquoi nous avons installé séparément sass
(le compilateur Dart Sass officiel), et que nous l’avons passé en paramètre via require('sass')
. Cette méthode est aujourd’hui recommandée et compatible avec les évolutions du langage. Pour plus de détails sur cette transition et les bonnes pratiques actuelles, la page officielle du projet est accessible ici : github.com/dlmanning/gulp-sass.
Exporter la tâche
Une fois notre tâche compileSCSS
prête, il nous reste à la rendre accessible depuis la ligne de commande, et à mettre en place un système de surveillance continue des fichiers .scss
. Cela nous permettra soit d’exécuter la compilation ponctuellement, soit de la déclencher automatiquement à chaque modification, ce qui est particulièrement utile en cours de développement.
// Rend la tâche accessible manuellement avec `npx gulp compileSCSS`
exports.compileSCSS = compileSCSS;
La première étape consiste à exporter explicitement notre fonction. Cela permet à Gulp de la reconnaître comme une tâche exécutable. Une fois exportée, on pourra la lancer directement avec une commande du type :
npx gulp compileSCSS
Cette approche, introduite avec Gulp 4, remplace les anciennes syntaxes basées sur gulp.task()
. Elle a l’avantage de clarifier la structure du fichier, en traitant les fonctions JavaScript comme des tâches déclarées. Pour en savoir plus sur cette évolution de Gulp et la gestion moderne des tâches, vous pouvez consulter la documentation officielle du projet gulp-sass
: github.com/dlmanning/gulp-sass.
Activer la surveillance
Nous allons ensuite mettre en place une fonction de surveillance, qui écoutera les changements dans nos fichiers .scss
et relancera automatiquement la compilation chaque fois qu’un fichier est modifié :
// Active la compilation automatique à chaque modification
function watchFiles() {
gulp.watch(paths.scss.src, compileSCSS); // observe tous les fichiers définis dans paths.scss.src
}
Enfin, nous définissons une tâche par défaut, qui exécute la compilation une première fois, puis démarre la surveillance. C’est cette tâche qui sera lancée si on exécute simplement npx gulp
, sans préciser de nom de tâche :
// Tâche par défaut : compile puis surveille les modifications
exports.default = gulp.series(compileSCSS, watchFiles);
Dès lors, un simple npx gulp
depuis la racine du projet suffit : la feuille de style est compilée une première fois, puis le système reste actif en arrière-plan. Chaque sauvegarde d’un fichier .scss
entraînera automatiquement une recompilation, la génération du fichier CSS optimisé et son écriture dans le dossier assets/css
.
Tester le fonctionnement : un premier fichier SCSS
Pour vérifier que tout est en place, nous allons créer un fichier style.scss
dans le dossier scss/
. Ce fichier contiendra quelques règles simples, organisées de manière typique en SCSS : utilisation de variables, de règles imbriquées et de commentaires. Voici un exemple minimal :
// scss/style.scss
$color-main: #577c57;
body {
font-family: sans-serif;
color: $color-main;
h1 {
font-size: 2rem;
text-transform: uppercase;
}
p {
line-height: 1.6;
margin-bottom: 1em;
}
}
Une fois ce fichier enregistré, il suffit de lancer Gulp avec la commande suivante, depuis la racine du projet :
npx gulp
Gulp exécute alors la tâche compileSCSS
, génère un fichier style.css
minifié dans assets/css/
, et crée également un fichier style.css.map
à côté. Ce second fichier est invisible pour l’utilisateur final, mais extrêmement utile pour nous, car il permet aux navigateurs de faire le lien entre le CSS généré et les lignes originales du SCSS. Cela facilite le débogage dans les outils de développement.
Dès lors, un simple npx gulp
depuis la racine du projet suffit :
la feuille de style est compilée une première fois, puis le système reste actif en arrière-plan. Chaque sauvegarde d’un fichier .scss
entraînera automatiquement une recompilation, la génération du fichier CSS optimisé et son écriture dans le dossier assets/css
.
Étendre l’automatisation : JavaScript, HTML… et transfert vers le serveur
Jusqu’ici, notre automatisation se limite à la compilation locale des fichiers SCSS, enregistrés dans assets/css/
. Mais dans un vrai projet, le but n’est pas seulement de générer ces fichiers : il faut aussi les mettre en ligne automatiquement à chaque mise à jour, pour éviter les transferts manuels fastidieux.
Dans cet article, nous n’irons pas encore jusqu’au traitement complet des fichiers JavaScript ou HTML, mais nous allons ajouter une brique importante : la publication FTP. Grâce à cela, chaque sauvegarde d’un fichier .scss
entraînera non seulement la compilation CSS, mais aussi son envoi immédiat sur le serveur distant.
Pour cela, nous allons installer deux modules supplémentaires :
npm install --save-dev vinyl-ftp fancy-log
vinyl-ftp
permet de créer une connexion FTP et de gérer les transferts de fichiers directement depuis Gulp, sans quitter l’environnement local.fancy-log
fournit un système de journalisation lisible dans le terminal, pour suivre clairement les étapes en cours, les transferts effectués ou les éventuelles erreurs.
Nous allons maintenant adapter notre gulpfile.js
pour intégrer cette nouvelle fonctionnalité, et compléter la tâche de surveillance pour qu’elle déclenche non seulement la compilation, mais aussi le déploiement automatique vers notre hébergement distant.
Préparer la configuration FTP
Pour pouvoir envoyer automatiquement nos fichiers CSS sur le serveur, nous allons maintenant compléter notre fichier gulpfile.js
. Il ne s’agit pas de tout réécrire, mais d’ajouter de nouveaux blocs, d’adapter la surveillance existante, et d’introduire une nouvelle logique de déploiement.
Commençons par l’ajout des deux modules nécessaires. Ils doivent être placés avec les autres require()
en haut du fichier :
// Ajout pour le transfert FTP
const vinylFtp = require('vinyl-ftp'); // gère la connexion et le transfert
const log = require('fancy-log'); // affiche proprement les actions dans le terminal
Nous allons ensuite définir les paramètres de connexion FTP. Il est préférable de le faire juste après la déclaration des chemins (const paths = {...}
), pour bien séparer les logiques.
// Configuration de connexion FTP
const ftpConfig = {
host: 'ftp.mondomaine.com', // Adresse de votre serveur FTP
user: 'utilisateur_ftp', // Identifiant FTP
password: 'motdepasse', // Mot de passe (à sécuriser ensuite)
port: 2121, // Port FTP (souvent 21 ou 2121 selon l'hébergeur)
parallel: 3, // Nombre de transferts simultanés
log: log // Utilisation du logger pour un affichage clair
};
Enfin, nous déclarons une variable séparée pour indiquer le chemin distant sur le serveur, celui dans lequel les fichiers CSS doivent être envoyés :
// Dossier distant sur le serveur
const remoteFolder = '/www/assets/css/';
Sécuriser les identifiants FTP dans un vrai projet
Dans les exemples précédents, nous avons inscrit les informations de connexion FTP directement dans le fichier gulpfile.js
. C’est parfaitement acceptable dans un cadre de test local ou pour des démonstrations pédagogiques. Mais dans un projet réel — surtout s’il est partagé, versionné avec Git, ou mis en production — cela pose un vrai risque de sécurité.
Conserver des identifiants en clair dans un fichier de configuration rend leur vol très facile, surtout s’ils se retrouvent dans un dépôt Git public ou envoyés par inadvertance à un tiers. Une bonne habitude à adopter dès le départ consiste à externaliser ces données sensibles.
Créer un fichier de configuration local
Une solution simple consiste à créer un fichier spécifique, par exemple ftp.config.js
, qui ne sera pas versionné. On y place uniquement les données de connexion, sous forme d’objet :
// ftp.config.js
module.exports = {
host: 'ftp.mondomaine.com',
user: 'utilisateur_ftp',
password: 'motdepasse',
port: 2121,
parallel: 3
};
On ajoute ensuite ce fichier dans le .gitignore
pour qu’il ne soit jamais suivi par Git :
echo "ftp.config.js" >> .gitignore
Charger la configuration depuis le gulpfile.js
Dans gulpfile.js
, on peut alors remplacer la déclaration manuelle par un simple require()
:
// gulpfile.js
const ftpCredentials = require('./ftp.config');
const vinylFtp = require('vinyl-ftp');
const log = require('fancy-log');
const ftpConfig = {
...ftpCredentials,
log: log
};
Ce mécanisme est simple, mais protège efficacement vos identifiants. Il a l’avantage d’être plus lisible qu’un fichier .env
, tout en restant compatible avec des outils plus complexes si besoin.
Créer la tâche de transfert FTP
Maintenant que la configuration FTP est prête, nous allons écrire une nouvelle fonction dans notre gulpfile.js
pour envoyer automatiquement les fichiers CSS générés sur le serveur distant.
L’objectif est simple : à chaque fois qu’un fichier .scss
est modifié, Gulp compile le SCSS, minifie le CSS, puis le transfère sans intervention manuelle. Cela permet de gagner un temps précieux et d’éviter les oublis ou erreurs de copie.
Sélectionner les bons fichiers
Nous voulons envoyer uniquement les fichiers .css
produits dans assets/css/
, tout en excluant les fichiers .map
générés par les sourcemaps. Voici comment nous construisons cette tâche :
// Tâche d’envoi FTP
function deployCSS() {
const conn = vinylFtp.create(ftpConfig); // crée une connexion FTP avec notre config
return gulp.src([
`${paths.scss.dest}/**/*.css`, // tous les fichiers CSS compilés
`!${paths.scss.dest}/**/*.map` // on exclut les fichiers .map
], { buffer: false }) // mode non-buffer pour les transferts FTP
.pipe(conn.dest(remoteFolder)); // envoie les fichiers vers le dossier distant
}
Chaque ligne a son rôle :
gulp.src([...])
définit les fichiers à transférer.- L’option
{ buffer: false }
optimise le transfert en FTP (les fichiers ne sont pas entièrement chargés en mémoire). .pipe(conn.dest(...))
lance le transfert effectif vers le serveur.
Pour rendre cette tâche exécutable directement depuis la ligne de commande, nous devons l’exporter explicitement :
exports.deploy = deployCSS;
Une fois cette ligne ajoutée dans le fichier gulpfile.js
, vous pourrez lancer la tâche manuellement avec :
npx gulp deploy
Cela déclenchera uniquement le transfert FTP, sans recompilation préalable. Cela peut être utile, par exemple, si vous avez déjà compilé le CSS et que vous souhaitez simplement le republier.
Enchaîner compilation et déploiement automatique
L’intérêt de Gulp ne réside pas uniquement dans l’exécution de tâches individuelles, mais dans sa capacité à enchaîner plusieurs opérations de manière fluide. Nous allons donc définir une nouvelle tâche qui commence par compiler notre SCSS, puis effectue immédiatement le transfert vers le serveur.
Créer une tâche combinée
Grâce à la méthode gulp.series()
, nous pouvons combiner plusieurs fonctions et les exécuter les unes après les autres :
// Tâche combinée : compile puis déploie
const buildAndDeploy = gulp.series(compileSCSS, deployCSS);
Ici, compileSCSS
est exécutée en premier. Une fois terminée sans erreur, Gulp enchaîne avec deployCSS
. C’est une série synchrone, adaptée à notre usage où chaque étape dépend de la précédente.
Mettre à jour la fonction de surveillance
Nous allons maintenant modifier la fonction watchFiles()
pour qu’elle ne lance plus seulement la compilation, mais le flux complet : compilation et publication.
// Tâche de surveillance continue
function watchFiles() {
gulp.watch(paths.scss.src, buildAndDeploy);
}
Dès que vous sauvegardez un fichier .scss
, Gulp :
- le compile en CSS minifié,
- puis envoie le fichier compilé sur le serveur.
Cette simple modification transforme votre poste de travail en chaîne de publication automatique.
Compléter les exports
Nous avons déjà rendu disponibles les tâches compile
et deploy
, que l’on peut exécuter individuellement depuis la ligne de commande. Il nous reste maintenant à déclarer :
- une tâche combinée
watch
, qui compile, déploie et surveille ; - une tâche
default
, qui sera exécutée si aucune tâche n’est précisée.
Voici les lignes à ajouter à la fin du fichier :
// Tâche combinée : compilation + déploiement + surveillance
exports.watch = gulp.series(buildAndDeploy, watchFiles);
// Tâche par défaut : identique à `watch`
exports.default = exports.watch;
Grâce à cette structure :
npx gulp compile
exécute uniquement la compilation ;npx gulp deploy
publie les fichiers CSS déjà compilés ;npx gulp
compile, publie et surveille en continu.
Votre gulpfile.js
est désormais complet, réactif, et prêt à être utilisé au quotidien dans un flux de travail automatisé.
Conclusion : un flux de base, à enrichir selon vos besoins
Nous avons mis en place un flux simple mais robuste : à chaque modification d’un fichier SCSS, Gulp se charge de le compiler, de l’optimiser, puis de le transférer automatiquement vers le serveur. Ce type d’automatisme transforme le quotidien : moins de gestes manuels, moins d’oublis, plus de cohérence.
Mais ce n’est qu’un début. Ce flux peut être étendu, adapté et personnalisé en fonction de la complexité de votre projet.
Dans deux prochains articles, nous verrons comment aller plus loin :
- en élargissant la surveillance à tous les fichiers utiles à un site web, qu’il s’agisse de JavaScript, HTML ou même d’images à optimiser ou déplacer ;
- en déclenchant automatiquement un rafraîchissement du navigateur à chaque mise à jour, pour visualiser les changements sans recharger la page à la main.
Ces évolutions s’intègrent naturellement à la structure déjà en place. Elles vous permettront de construire un environnement de travail plus fluide, plus vivant, et toujours adapté à votre façon de coder.