hs0ucy Aller au menu de navigation

CSS et Unix

Regrouper plusieurs feuilles de styles ensemble sous Unix

À des fins de performance, cela peut-être une bonne idée de regrouper nos feuilles de styles pour réduire le nombre de requêtes HTTP.

Si avec HTTP 1.1, c'était bien vue de ne servir qu'un seul fichier CSS. Avec HTTP 2, il est conseillé de découper ses feuilles en plusieurs ballots hiérarchisés, plutôt qu'en un seul gros bloc de code.

À ce sujet, voir le banc d'essai de Harry Roberts: CSS and Network Performance.

Règle @import

La règle CSS @import, n'est pas conseillé en production pour justement une question de performance.

Alors quelle autre option nous reste-t-il si on veut découper nos styles sans passer par un préprocesseur?

Utilitaire cat

Pour concaténer des fichiers ensemble sous Unix il faut utiliser l'utilitaire cat.

cat - concatenate and print files

Avec peu de fichiers CSS, on peut simplement faire:

cat a.css b.css c.css d.css e.css f.css > styles.css

En voulant être plus concis cela serait:

cat *.css > styles.css

Mais en CSS l'ordre des déclarations est important. Nous ne voudrions pas neutraliser ou déclasser certains styles.

Dans les utilitaires du shell il y a un flux entrant (standard input ou stdin) et un flux sortant (standard output ou stdout). La lecture se fait par le stdin et l'écriture par le stdout. Il y a aussi un flux sortant pour les erreurs (standard error ou stderr).

Il est toutefois possible détourner ces flux. Comme par exemple avec < ou > en appliquant des redirections vers un fichier, comme dans mon exemple ci-haut, avec l'utilitaire cat, où l'on redirige la sortie vers le fichier styles.css. Sans cette redirection le résultat s'afficherait dans le terminal avec stdout.

La redirection d'entrée utilise le symbole <. Cela permet d'indiquer qu'un fichier sera passé en stdin.

Concaténer une liste de CSS avec while, read et <

Maintenant nous allons utilser une boucle de type while, combiné avec l'utilitaire read, pour concaténer un groupe de fichiers CSS.

Notre liste se trouve dans un fichier nommé global-styles.txt. Nous y avons inscrit une feuille de style par ligne:

global/tokens/typography.css
global/tokens/colors.css
global/tokens/grid.css

global/base.css
global/a11y.css

Ensuite, notre script sera dans un autre fichier que nous appellerons css.sh:

#!/bin/sh

while read -r line; do
  [ -n "$line" ] && cat "./$line"
done < global-styles.txt

Attention, il est important de s'assurer que ce fichier soit exécutable (chmod u+x css.sh), avant de lancer la commande:

./css.sh

Si tout s'est bien passé, on constate que le contenu de toutes les feuilles que nous avons listées s'affichent dans le terminal.

Dans ce script, la valeur de chaque ligne est assignée à la variable line. Puis [ -n "$line" ], teste si la chaîne de caractère retournée par $line n'est pas null avant de d'exécuter cat. Et finalement, notre liste est dirigée dans la boucle avec <.

L'étape suivante serait de rediriger stdout vers un fichier CSS avec >:

#!/bin/sh

while read -r line; do
  [ -n "$line" ] && cat "./$line"
done < global-styles.txt > global.css

On pourrait aussi ne pas vouloir de fichier .txt et lister directement dans le script les fichier à concaténer:

#!/bin/sh

while read -r line; do
  [ -n "$line" ] && cat "./$line"
done <<EOF
global/tokens/typography.css
global/tokens/colors.css
global/tokens/grid.css

global/base.css
global/a11y.css
EOF

Ici EOF est une commande qui permet de faire une entrée multiligne. Donc toutes les lignes qui se trouve entre <<EOF et EOF est passé à stdin.

Minifier une feuille de style avec tr pour réduire son poid

L'utilitaire tr sert à traduire ou éliminer des caractères. Il va permettre de retirer les sauts de ligne et les retours dans notre CSS, pour ramener toutes les règles sur une seule ligne. Le poid du fichier sera donc un peu moindre:

cat global.css | tr -d '\n\r' > "$global.min.css"

Ce n'est pas la façon la plus optimale de minifier, mais avec plusieurs feuilles style cela permet de faire des gains de plusieurs kilooctets. Sinon avec l'utilitaire sed, il est sans doute possible d'améliorer la soustraction.

Le caractère |, que l'on appelle pipe, sert à lier deux processus en prenant le flux de sortie du premier, pour en faire le flux d'entrée du second.

Rendu ici, on peut mettre ensemble la concaténation et minification:

#!/bin/sh

while read -r line; do
  [ -n "$line" ] && cat "./$line"
done <<EOF | tr -d '\n\r' > "global.min.css"
global/tokens/typography.css
global/tokens/colors.css
global/tokens/grid.css

global/base.css
global/a11y.css
EOF