Quand vous développez un thème ou une extension pour WordPress, il y a de grandes chances que vous ayiez besoin d’outils CLI, que ce soit pour compiler vos fichiers Sass, minifier vos ressources CSS et JS, générer des fichiers JSON ou .pot, packager votre extension, etc… Il existe des centaines d’outils CLI et de packages pour ces tâches répétitives (et donc automatisables), dans tous les langages possibles.

Dans cet article on va voir comment utiliser de simples scripts npm pour créer des raccourcis et automatiser ses tâches de développement récurrentes quand vous codez vos extensions ou thèmes WordPress.

Node, npm et tasks runners

Pour rappel, NodeJS est un runtime pour JavaScript. Il permet simplement d’exécuter du JavaScript sur votre ordinateur. Et npm est son package manager, c’est-à-dire un outil qui permet de gérer les packages JavaScript installés de façon globale (sur votre ordinateur, accessible globalement) et locale (dans votre projet).

Il y a de grandes chances que vous ayiez déjà Node et npm installés sur votre machine, mais si ce n’est pas le cas, rendez-vous sur https://nodejs.org/fr/ pour les télécharger et les installer.

Il existe plusieurs outils permettant d’automatiser ses tâches de développement, comme Gulp ou Grunt. Ces outils permettent de créer des successions et enchaînements de tâches longs, complexes et entièrement paramétrables, mais demandent un certain travail de configuration et sont d’une certaine complexité.

Personnellement, pour la majorité des développements que je fais, configurer un outil de ce type ne vaut pas le coup. C’est long et compliqué. Par contre, npm permet de personnaliser de petits raccourcis bien utiles !

Je vous montre ça en détails maintenant !

Compiler vos fichiers Sass

Si vous écrivez du CSS, vous utilisez peut-être un préprocesseur de CSS, comme Sass, Less ou Stylus.

Pour mes thèmes, si je veux compiler ma feuille de style style.scss de mon dossier sass/ dans le fichier style.css à la racine du thème, j’ouvre un terminal et j’utilise la commande dart-sass suivante :

sass --watch sass/style.scss:style.css

La commande démarre le watcher qui va surveiller mon fichier et le recompiler à chaque fois qu’il va être modifié. C’est pratique.

Si j’ai une autre feuille de styles dans mon thème pour les pages produits WooCommerce par exemple (sass/woocommerce.scss), je dois ouvrir un autre terminal et taper ceci :

sass --watch sass/woocommerce.scss:woocommerce.css

Le souci est qu’à chaque fois que je m’installe pour une session de développement, je dois de nouveau ouvrir deux terminaux et taper ces deux commandes. Vous imaginez les proportions que cela peut prendre au fur et à mesure que le projet se complexifie, et que vos besoins de processing pendant le développement augmentent.

Créer des scripts NPM pour se simplifier les développements

Commençons par créer un fichier package.json. Ce fichier contiendra les informations sur votre projet utiles pour npm, comme la version, les scripts ou les dépendances. Ouvrez un terminal à la racine de votre projet, et tapez la commande suivante :

npm init

npm vous posera quelques questions pour mettre en place le fichier package.json. Vous pouvez laisser les réponses par défaut en appuyant sur Entrée. Pour mon thème Voyager, créé dans la formation Développer son thème WordPress, cela donne ceci :

// package.json
{ 
    "name": "voyager",
    "version": "1.0.0",
    "description": "Theme used as an example for Développer son thème WordPress",
    "main": "index.js", 
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    "author": "Vincent Dubroeucq",
    "license": "GPL-3.0-or-later"
}

Ce qui nous intéresse ici, c’est le contenu de l’entrée scripts. On peut y ajouter toute commande utile, pour pouvoir ensuite l’exécuter simplement à l’aide de npm run [commande]. Ajoutons donc une entrée style:watch avec un raccourci pour compiler notre feuille de style :

// package.json
{
    ...
    "scripts": {
        "style:watch" : "sass --watch sass/style.scss:style.css"
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    ...
}

Maintenant, au lieu d’ouvrir un terminal et de taper la longue commande sass --watch sass/style.scss:style.css, je peux simplement taper npm run style:watch et mon script associé s’exécutera ! C’est déjà plus rapide, et le risque d’erreur est moindre, vu qu’on n’a eu à taper la longue commande qu’une seule fois.

Si j’ai une feuille de style pour l’éditeur ou pour WooCommerce, je peux créer des raccourcis similaires :

// package.json
"scripts": {
    "style:watch": "sass --watch sass/style.scss:style.css",
    "editor-style:watch": "sass --watch sass/editor-style.scss:editor-style.css",
    "woocommerce-style:watch": "sass --watch sass/woocommerce.scss:woocommerce.css",
},

C’est déjà bien plus simple, mais on a toujours besoin d’ouvrir trois terminaux. On peut exécuter les tâches simultanément dans le même terminal, en utilisant l’opérateur &, comme ceci :

// package.json
"scripts": {
    "sass:watch": "npm run style:watch & npm run editor-style:watch & npm run woocommerce-style:watch",
    "style:watch": "sass --watch sass/style.scss:style.css",
    "editor-style:watch": "sass --watch sass/editor-style.scss:editor-style.css",
    "woocommerce-style:watch": "sass --watch sass/woocommerce.scss:woocommerce.css",
},

La commande sass:watch permet d’exécuter les trois scripts en parallèle. Ce qui est intéressant à noter ici est que dans chaque script npm, on peut appeler d’autres scripts npm. C’est très utile.

Maintenant, démarrer une session de développement se fait en une seule commande, et mes trois feuilles de styles sont surveillées et automatiquement recompilées. C’est très simple, et vous pouvez faire de même pour toutes les autres tâches que vous souhaitez automatiser pendant votre développement.

Préparer votre thème ou extension pour la production

Sur le même principe, on peut créer une série de tâches simples qui vont nous aider à préparer notre thème ou extension pour sa publication ou mise en production.

Créer votre fichier POT

Créer des fichiers de traductions pour votre thème ou extension est faisable très facilement si vous avez WP-CLI installé. Une seule commande suffit :

wp i18n make-pot . languages/voyager.pot

Mais c’est encore mieux quand on a un raccourci dans notre fichier package.json :

// package.json
"scripts": {
    ...
    "make-pot" : "wp i18n make-pot . languages/voyager.pot",
}

Maintenant, il suffit de taper :

npm run make-pot

npm permet ici d’exécuter une commande WP-CLI. Magic.

Traiter votre JavaScript

Dans mon thème, j’ai un petit fichier JS navigation.js qui est responsable du comportement du bouton de navigation et qui ouvre ou ferme le menu mobile. J’aimerais m’assurer que ce fichier écrit en JavaScript moderne soit compatible pour tous les navigateurs, même anciens, donc j’aimerais utiliser Babel pour transpiler mon JavaScript moderne en Javascript compatible.

BabelJS fournit un outil CLI en JavaScript. On va donc l’installer en suivant la documentation. Dans mon terminal, je tape :

npm install --save-dev @babel/core @babel/cli @babel/preset-env

Cela installe le cœur de l’outil, le CLI et le preset dans le dossier node_modules/ de mon projet. Le preset est en quelque sorte une configuration par défaut pour transformer le JavaScript moderne en JavaScript compréhensible par tous les navigateurs.

Puis j’ajoute un script qui va utiliser Babel sur mon fichier JavaScript.

// package.json
"scripts": {
    ...
    "babel": "babel --presets=@babel/preset-env js/navigation.js -o js/navigation.babel.js",
}

L’option -o permet de spécifier le fichier de sortie, simplement. Maintenant, si je lance le script avec npm run babel, je peux constater que mon fichier js/navigation.babel.js est différent de mon original : les fonctions fléchées sont remplacées par des déclarations de fonctions normales et mes déclarations de variable const sont remplacées par des var, mais le script fonctionne de la même façon.

Ici, la commande effectue la transformation une seule fois, mais ne surveille pas vos fichiers. Si vous voulez surveiller vos fichiers pour les transformer à chaque sauvegarde, vous pouvez aussi utiliser une option --watch.

// package.json
"scripts": {
    ...
    "babel": "babel --presets=@babel/preset-env js/navigation.js -o js/navigation.min.js",
    "babel:watch": "babel --watch --presets=@babel/preset-env js/navigation.js -o js/navigation.babel.js",
}

Maintenant, on peut minifier notre JavaScript après l’avoir transformé avec Babel. On peut par exemple utiliser le package terser. Il s’installe simplement :

npm install terser --save-dev

Puis on ajoute la commande correspondante dans package.json :

// package.json
"scripts": {
    ...
    "terser": "terser js/navigation.babel.js -o js/navigation.min.js"
}

Ici, on cible le fichier navigation.babel.js, car on souhaite minifier la version transformée par Babel.

Pour éviter d’avoir un fichier intermédiaire inutilisé, on peut aussi ajuster les commandes comme ceci :

// package.json
"scripts": {
    ...
    "babel": "babel --presets=@babel/preset-env js/navigation.js -o js/navigation.min.js",
    "terser": "terser js/navigation.min.js -o js/navigation.min.js"
}

Babel va transformer notre fichier navigation.js dans navigation.min.js, et terser va minifier ce même fichier.

Minifier votre CSS

Une fois votre SCSS compilé, vous voudrez probablement aussi compresser ou minifier le CSS avant de publier votre thème ou extension. Vous pouvez soit utiliser le paramètre Dart Sass prévu à cet effet pour compresser vos styles ou un outil dédié comme PostCSS et CSSNano pour le minifier.

Dart Sass propose un paramètre --style qui va permettre de compresser votre feuille de style.

// package.json
"scripts": {
    ...
    "style:build": "sass --style=compressed sass/style.scss:style.min.css",
}

En lançant npm run style:build, une nouvelle feuille de style compressé style.min.css est créée, à partir du fichier source style.scss.

Si vous avez besoin d’une minification ou d’un traitement CSS plus complexe, CSSNano est une solution simple.

npm install --save-dev postcss postcss-cli cssnano

PostCSS est un outil qui peut traiter vos fichiers CSS de nombreuses façon différentes et qui fonctionne par plugins. Chaque plugin va permettre d’effectuer un traitement spécial sur votre CSS. CSSNano est un plugin PostCSS qui va minifier votre CSS. C’est très puissant, mais cela demande un peu plus de configuration.

Créez un ficher de configuration nommé postcss.config.js à la racine de votre projet et collez-y le code suivant :

module.exports = {
    plugins: [
        require('cssnano')({
            preset: 'default',
        }),
    ],
};

Ajoutez le raccourci dans package.json :

// package.json
"scripts": {
    ...
    "postcss": "postcss style.css > style.min.css"
}

Si vous lancez npm run postcss dans votre terminal, cela créera un fichier style.min.css, minifié selon les paramètres contenu dans le fichier de configuration. Easy.

Combiner les scripts

On a vu comment on peut créer des raccourcis pour les tâches de développement courantes via les scripts dans package.json, mais on doit quand même ouvrir un terminal et taper ces commandes successivement si on doit traiter nos fichiers pour les préparer à la production.

Par exemple, compiler nos fichiers SCSS et minifier notre CSS demande plusieurs commandes : npm run style:watch, npm run editor-style:watch et npm run woocommerce-style:watch pendant le développement, puis npm run style:build ou npm run postcss pour minifier notre feuille principale.

On peut aussi imaginer qu’on aura besoin de npm run editor-style:build et npm run woocommerce-style:build pour minifier nos autres feuilles CSS.

Idem pour le JavaScript : on a besoin de npm run babel puis npm run terser pour transpiler et compresser notre script.

Cela reste pénible. Moins que de taper toutes les commandes une à une, certes. Mais on peut faire mieux que ça.

De la même façon qu’on a combiné nos scripts *:watch, on peut combiner nos scripts de build.

// package.json
"scripts": {
    "css:build": "npm run style:build & npm run editor-style:build & npm run woocommerce-style:build",
    "js:build": "npm run babel && npm run terser",
}

Ici, avec une seule commande npm run css:build, on compile et compresse les trois feuilles de styles. Les trois tâches peuvent être effectués en parallèle car les fichiers sont indépendants.

Par contre la commande npm run js:build va transformer notre JavaScript à l’aide de Babel PUIS minifier le fichier navigation.min.js obtenu. Les deux tâches doivent être exécutées l’une après l’autre, ce qui est indiquée ici par l’opérateur &&.

start et build

Par convention dans les applications JavaScript, les scripts start et build sont utilisés comme raccourcis pour lancer toutes les tâches de développements et de production, respectivement.

On va donc adopter cette convention et créer un script start qui va lancer tous les processus nécessaires pendant le développement (dans notre cas, seul la compilation automatique des fichiers SCSS est nécessaire) :

// package.json
"scripts": {
    ...
    "start": "npm run sass:watch",
}

Dans notre exemple cela suffit, mais si on a besoin de traiter automatiquement le JavaScript pendant le développement, il suffit d’enchaîner une autre commande avec &.

On va aussi créer un script build qui va s’occuper de minifier tous nos fichiers et créer notre fichier pot.

// package.json
"scripts": {
    ...
    "build": "npm run css:build & npm run js:build & npm run make-pot",
}

Une fois toutes ces tâches mises en place, à chaque session de développement, il vous suffira d’ouvrir votre projet et de lancer npm run start ou npm start pour lancer le développement de votre projet. Et quand vous aurez terminé, un npm run build suffira pour préparer vos fichiers CSS, JS, et POT pour la production. C’est pas mieux ?

Vers l’infini et au-delà !

Vous pouvez pousser cela aussi loin que vous voulez, selon votre envie ou besoin : compresser vos images, formatter vos fichiers PHP et CSS, générer une feuille de style RTL, créer une archive zip, etc… Il existe des packages et outils pour toutes sortes de tâches imaginables.

Le principe pour d’automatiser ses tâches de développement est au final assez simple :

  • on crée un fichier package.json grâce à npm init
  • on crée des raccourcis vers les différents outils CLI que l’on utilise pour traiter les fichiers de notre projet,
  • on compose notre propre ligne de production en combinant et enchaînant les tâches :
    • avec l’opérateur & pour les tâches à exécuter tâches en parallèle
    • avec l’opérateur && pour les tâches à exécuter de manière séquentielle

L’avantage d’utiliser des scripts npm est que vous pouvez facilement les copier-coller d’un projet à l’autre et créer votre process personnalisé que vous allez réutiliser et affiner au fur et à mesure.

Si vous souhaitez voir ça en action pendant le développement d’un thème, jetez un oeil à Développer son thème WordPress. Vous y apprendrez non seulement comment développer des thèmes WordPress proprement en respectant tous les standards de WordPress, mais aussi comment organiser simplement vos développements et créer ce process simple, pas à pas.

J’espère vous avoir aidé !

Enjoy !