Child-Thème, gérer les dépendances
Lors d’un précédent article, Créer un thème enfant pour WordPress, nous avions vu comment gérer les insertions des diverses feuilles de styles, parent et enfant. Voyons à présent comment organiser de manière plus avancée l’ensemble des éventuelles dépendances, fussent-elles CSS aussi bien que JavaScript.
Il est donc possible d’inclure, et utiliser, d’autres fichiers, provenant aussi bien du thème parent que du thème enfant, et les seules notions à prendre en considération vont être, la priorité de chargement et la base d’accès au dossier à prendre en considération. À l’inverse, il est également possible de ne plus faire appel à certains fichiers, cette fois ci, exclusivement du thème parent et donc de les retirer du document.
Pourquoi devoir gérer les dépendances ?
Les dépendances sont tous ces fichiers, aussi bien styles que scripts, qui sont nécessaires afin de pouvoir utiliser au mieux les frameworks, ou libraires, qu’ils représentent. Donc un thème parent peut tout aussi bien d’un coté utiliser des fichiers développés pour ses propres besoins internes, et pouvant être répartis en diverses déclinaisons (layout, typo, fonctionalités, composants,…), mais d’un autre coté le thème peut également faire référence aux fichiers nécessaires par de tierces applications, comme Bootstrap, Foundation, eux mêmes pouvant également avoir leurs propres dépendances (response.js, jQuery…).
Bref, la complexité va donc venir de pouvoir relier l’ensemble de ces fichiers à notre thème enfant sans pour autant les dupliquer en les liant de multiples fois à notre document, mais aussi et surtout sans en oublier si ceux ci n’étaient pas correctement, et automatiquement, pris en charge.
De manière générale, les thèmes disponibles sur le marché aujourd’hui gèrent eux même leurs propres dépendances en interne et donc de ce coté nous n’avons pas grand chose à faire, sauf dans certains cas, tels que :
- Le thème parent ne gère pas ses dépendances depuis le fichier functions.php et par exemple le thème importe l’ensemble de ses styles en usant de @import, ou directement depuis le fichier header.php notamment au travers de balises <link> ou ses scripts depuis des balises <script> l’ensemble ancré en dur dans le code
- Le thème enfant peut avoir besoin en amont de une, ou plusieurs, dépendance(s) propre au thème parent, et donc nécessite une anticipation de chargement
- Il est également parfois nécessaire de retirer certaines dépendances du thème parent qui ne seront plus utilisées par le thème enfant
- …
De plus, il existe une autre question à se poser au niveau de l’ensemble des dépendances, à savoir, est qu’on utilise un mécanisme de compilation automatique (Préprocesseurs, Automatiseur de tâches, PostCSS…) et/ou s’appuie-t-on sur un gestionnaire de dépendances (bower, npm, Jam, Ender…). Si tel est le cas, ne serait-il pas judicieux de coupler cette gestion automatisée et prendre en compte les fichiers du coté du thème parent ?
Comment gérer ses dépendances ?
Ceci-dit, la gestion des dépendances multiples n’est pas vraiment complexe en soit. Coté WordPress, il suffit simplement d’utiliser une fonction wp_enqueue_style() pour les feuilles de styles et/ou une fonction wp_enqueue_script() pour les fichiers JavaScript. Ces instructions pointeront vers l’ensemble des dépendances nécessaires.
wp_enqueue_style( identifiant, chemin d'accès, dépendances, version, requête de média); wp_enqueue_script( identifiant, chemin d'accès, dépendances, version, place d'insertion du script );
wp_enqueue_style() | wp_enqueue_script() | description | |
---|---|---|---|
identifiant | x | x | identifiant du bloc dans le DOM |
chemin d’accès | x | x | chemin d’accès au fichier source |
dépendances | x | x | liste les dépendances nécessaires au fichier |
version | x | x | défini l’utilisation, ou non, d’une version |
requête de média | x | précise une media query de liaison | |
place d’insertion du script | x | indique si le script s’insère dans le <head> ou avant la fermeture du </body> | |
Autres fonctions: wp_dequeue_style(), wp_dequeue_script(), wp_register_style(), wp_register_script(), wp_deregister_style(), wp_deregister_script() Hooks: wp_enqueue_scripts, style_loader_tag, script_loader_tag |
Parfois, si un grand nombre de fichiers sont à prendre en compte, il peut être nécessaire d’ajouter un indice de priorité au hook utilisé. Si vous souhaitez vous assurer que le fichier soit chargé en dernier, placer une priorité très élevé en utilisant PHP_INT_MAX. Rapprochez vous de l’article Créer un thème enfant pour WordPress et/ou de l’article Charger scripts et styles dans WordPress.
Attention aux chemins utilisés
Rappelons que lorsque nous souhaitons pointer vers un fichier situé dans le dossier du thème enfant, il nous faut alors employer l’instruction get_stylesheet_directory(). En effet la feuille de style en cours d’utilisation étant dans le dossier du thème enfant, cette instruction nous renverra bien le chemin concernant le dossier du thème enfant. Alors que si nous souhaitons pointer vers le dossier du thème parent, qui correspond clairement au thème réellement en cours d’utilisation, il nous faudra alors user de get_template_directory().
Ne pas confondre avec les fonctions homologues telles que get_stylesheet_directory_uri() et get_template_directory_uri() qui elles renverront les URLs, au lieu des chemins de fichiers. De même pour get_stylesheet_uri() qui retournera l’URL du fichier de styles CSS utilisé. En résumé :
Fonctions | Affecte | Renvoie |
---|---|---|
get_stylesheet_directory_uri() | child | http://www.domaine.ext/wp-content/themes/theme-enfant |
get_stylesheet_directory() | child | /home/user/public_html/wp-content/themes/theme-enfant |
get_stylesheet_uri() | child | http://www.domaine.ext/wp-content/themes/theme-enfant/style.css |
get_template_directory_uri() | parent | http://www.domaine.ext/wp-content/themes/theme-parent |
get_template_directory() | parent | /home/user/public_html/wp-content/themes/theme-parent |
Travaillons autour de quelques exemples
Tout ceci est bien beau, mais cela peut paraître bien souvent confus, et, il est vrai que la littérature sur le sujet présente toujours à la pelle ce même type de fonctions, sans pour autant mettre en cas d’école en pratique. Donc une fois encore ouvrez un bac à sable, activez si besoin un plugin de débogage et assistez vous de divers thèmes de travail.
Première démarche, toujours faire l’état des lieux
Bon, commençons par mettre en place un thème enfant s’appuyant sur le thème Twenty Seventeen. Il est important de ne rien ajouter à ce thème enfant si ce n’est la déclaration minimale en commentaires.
/*! Theme Name: Thème basé sur Twenty Seventeen Template: twentyseventeen */
Puis activons ce thème, affichons le rendu de la page et vérifions le code source.
Alors, qu’avons nous ? Entre la ligne 34 et la ligne 45, nous pouvons constater que bien que le rendu du site soit un HTML brut de décoffrage, tout un certains nombre de dépendances ont été chargées, et ce, sans que nous ne demandions quoique ce soit. Alors qu’est ce qui a été chargé, au niveau des styles CSS et des scripts JavaScript qui sont donc propres au thème parent ?
- Ligne 34 – Des Dashicons – #dashicons-css – (CSS)
- Ligne 35 – La barre d’admin -#admin-bar-css- (CSS)
- Ligne 36 – Les fontes -#twentyseventeen-fonts-css- (CSS)
- Ligne 37 – La feuille de style enfant -#twentyseventeen-style-css- (CSS)
- Ligne 39 – Les styles pour ie8 -#twentyseventeen-ie8-css- (CSS), en commentaires conditionnels
- Ligne 42 – Les scripts pour ie8 – (JavaScript), en commentaires conditionnels
- Ligne 44 – jQuery – (JavaScript)
- Ligne 45 – jQuery migrate – (JavaScript)
En fait, l’ensemble de ces éléments ont été mis en place par la fonction twentyseventeen_scripts() qui se situe à la ligne 410 du fichier functions.php du thème parent, exceptés les deux liens vers jQuery qui proviennent directement du dossier wp-includes, chargés par le fichier script-loader.php à partir de la ligne 185, et, qui donc font quelque part partie du cœur de WordPress.
Mettre en place la fonction de chargement
Nous avions vu au cours d’un précédent article Créer un thème enfant pour WordPress, un script générique qui permet la gestion fine des divers ajouts, notamment celui du style thème parent et celui du style thème enfant tout en prenant en compte la dépendance de l’un par rapport à l’autre, pour mémoire :
<?php function charge_styles() { $dependances = array( ); $dependances[] = 'style-parent'; wp_enqueue_style( 'style-parent', get_template_directory_uri() . '/style.css' ); wp_enqueue_style( 'style-enfant', get_stylesheet_directory_uri() . '/style.css', $dependances ); } add_action( 'wp_enqueue_scripts', 'charge_styles' ); ?>
Ajoutons donc ce script au fichier functions.php de notre thème enfant et rechargeons simplement le code source de la page qui devrait ainsi s’actualiser. Et là, nous pouvons voir, en lignes 36 et 37, apparaître nos deux nouveaux liens de chargements, le thème enfant se chargeant bien après le thème parent.
Mais à y regarder de plus près, nous avons maintenant deux fois les styles du thème enfant qui se chargent, une fois celui que nous venons d’ajouter en ligne 37, qui use de l’identifiant style-enfant-css, et, une fois, certainement pris en compte par le thème parent, en ligne 39, avec cette fois-ci pour identifiant twentyseventeen-style-css. Il y a comme qui dirait un script en trop… donc conclusion, il n’est pas nécessaire de charger le thème enfant, pour ce thème ci.
Comme nous le présentons dans un autre article, Organiser ses styles dans un thème enfant, il est tout à fait possible de libérer la feuille de style de base style.css et d’utiliser en complément une autre feuille de style, indépendante, par exemple style-enfant-global.css. Cette feuille pourrait rassembler l’ensemble des styles nécessaires, entre l’affichage, la gestion des typos, l’approche des divers composants … etc, etc…. De ce fait nous aurions d’un coté le style de base qui lui gère la prise en compte du thème enfant et de sa relation avec le thème parent, et d’un autre coté, la centralisation des styles ‘globaux’ qui gèrent l’aspect rendu général du thème de manière indépendante.
Si tel est le cas, nous pouvons alors simplement remplacer le nom du fichier CSS à charger dans notre fonction précédente, et de ce fait au lieu de pointer vers ‘/style.css’, nous pouvons alors orienter vers ‘/style-enfant-global.css’, (ou tout autre fichier prenant en compte cette centralisation).
Ajouter avant ou après ?
Par défaut, nous voyons également que les deux fichiers de styles se sont chargés après, ceux concernant l’interface d’administration, mais avant ceux employés par le thème parent. Nous pouvons agir sur l’ordre de chargement des fichiers, et ce, de deux manières. La première, en jouant avec les dépendances, et la seconde, en changeant l’indice de priorité lors de l’utilisation du hook qui lance la fonction.
De même, et au cours d’exécution de cette même fonction, nous pouvons charger également des fichiers JavaScript qui seraient nécessaires au thème enfant. Il est également possible de retirer des styles, chargés par le thème parent, et qui, ne nous seraient plus utiles. Créons les fichiers scripts.js, style-enfant-global.css et dispatch.css, (même s’ils sont vides de contenus), nous pourrons ainsi les utiliser pour continuer nos tests. Améliorons donc la fonction.
<?php function charge_fichiers() { $dependances = array( ); $dependances[] = 'style-landscape'; $media-landscape = '(orientation: landscape) and (min-width: 640px)'; wp_enqueue_style( 'style-parent', get_template_directory_uri() . '/style.css' );// #I wp_enqueue_style( 'style-enfant', get_stylesheet_directory_uri() . '/style-enfant-global.css', $dependances ); // #B wp_register_script( 'script-enfant', get_stylesheet_directory_uri() . '/script.js', array(), null, false); // #E, #G wp_enqueue_script( 'script-enfant'); // #E wp_dequeue_style( 'twentyseventeen-style'); // #D wp_deregister_style('twentyseventeen-style'); // #H wp_register_style( 'style-landscape', get_stylesheet_directory_uri() . '/dispatch.css',array(), false, $media-landscape ); // #B, #C, #F } add_action( 'wp_enqueue_scripts', 'charge_fichiers', PHP_INT_MAX); // #A ?>
Rechargeons le code source pour en vérifier la bonne application. Nous voyons bien que (et sans respecter un ordre particulier pour les remarques qui vont suivre) :
- [#A] – Les styles et scripts sont chargés en dernier lieu, dû à la présence du paramètre de priorité placé sur PHP_INT_MAX, qui lancera cette action en dernier lieu
- [#B] – Le style-landscape est chargé avant le style-enfant, cela est du au paramètre de dépendance, et ce, bien que l’ordre des commandes soient dans un ordre inverse.
- [#C] – Le style-landscape utilise son dernier paramètre pour définir la requête de média à utiliser pour lier la feuille de style
- [#D] – Le style twentyseventeen-style a été retiré
- [#E] – Le script script-enfant a d’abord été enregistré, puis il a suffit d’user d’un wp_enqueue_script simplement pointant vers son identifiant pour le charger
- [#F] – Le script style-landscape a simplement été enregistré, mais le fait de le placer dans une dépendance revient à le charger également
- [#G] – Le script-enfant est bien chargé en entête du fichier HTML, par contre si vous placez le dernier paramètre sur la valeur true, celui-ci se chargera juste avant la fermeture de la balise </body>
- [#H] – Il a été nécessaire de désenregistrer le style twentyseventeen-style afin de pouvoir réellement retirer ce style
- [#I] – Il est nécessaire de charger le style style-parent pour importer le style du thème parent
Isoler le déchargement des scripts
Il ne vous reste plus qu’à affiner la fonction de gestion des chargements de fichiers pour l’adapter à vos besoins. Vous remarquerez, qu’il se peut que certains styles, ou scripts, ne se détachent pas si facilement. Par exemple, dans la fonction précédente, il a été nécessaire de désenregistrer le script [#H], pour retirer correctement le style twentyseventeen-style. En fait, il ne suffit pas simplement de rajouter la demande de désenregistrement, il faut également s’assurer d’invoquer la fonction avec un indice de priorité élevé, pour voir la ligne du lien retirée du code. Ci dessous, la fonction (isolée) qui est nécessaire pour décharger le script
<?php function decharge_fichiers() { wp_dequeue_style( 'twentyseventeen-style'); wp_deregister_style('twentyseventeen-style'); } add_action( 'wp_enqueue_scripts', 'decharge_fichiers', PHP_INT_MAX ); ?>
Ajouter des attributs
Le code ainsi généré est fonctionnel mais cependant il n’existe pas, à l’instar des styles, d’identifiant qui soit ajouté aux diverses balises <script>. Ceci peut être gênant si nous avons besoin d’intervenir sur le DOM à ce niveau. Nous allons pouvoir intercepter au travers d’un hook de type filtre script_loader_tag la génération du code et pouvoir ainsi ajouter explicitement ces identifiants. Nous pourrions, si besoin était, améliorer cette fonction en filtrant au travers d’un tableau (array()), uniquement les scripts que nous souhaiterions affecter par l’ajout.
<?php function ajoute_id_scripts( $balise, $id, $src ) { $scripts_liste = array( 'html5', 'script-enfant' ); if ( in_array( $balise, $scripts_liste ) ) { return '<script type="text/javascript" id="'.$id.'" src="' . $src . '" ></script>'."\n"; } else { return $balise; } } add_filter( 'script_loader_tag', 'ajoute_id_scripts', 10, 3 ); ?>
Et si on se passe du thème parent ?
Attention, si le thème enfant évolue à un point de pouvoir se passer du thème parent, il peut être intéressant alors d’anticiper cette éventualité en s’assurant de ne charger les dépendances du thème parent que si le thème enfant n’est pas lui-même, le thème principal.
<?php function gere_styles() { $dependances = array(); if (is_child_theme()) { $dependances[] = 'style-parent'; wp_enqueue_style('style-parent', get_template_directory_uri() .'/style.css'); } wp_enqueue_style('style-theme', get_stylesheet_uri(), $dependances); } add_action('wp_enqueue_scripts', 'gere_styles'); ?>