accueil   blog   bin   contact

Compression et minification d'un site statique avec smc

Étude d'un site créé par ssg5

ssg5 crée un site web composé de pages au format html, accompagnées au besoin d'une ou plusieurs feuilles de style css. Ces fichiers sont généralement assez petits, mais nombreux. ssg5 crée également une carte du site au format xml, et rssg ou brg génèrent un fil RSS également au format xml. Ces deux fichiers deviennent vite volumineux avec l'augmentation du nombre de page du site.

Ces fichiers ont tous un point commun : ils contiennent des informations qui se répètent, leur compression apportera un gain important en termes de taille. Aussi, ils peuvent contenir des caractères non indispensables à leur interprétation par un navigateur, comme des tabulations d'indentation ou des commentaires, il peut donc être utile de les supprimer avant de les téléverser sur le serveur assurant leur mise à disposition sur le web.

Au bilan, on retiendra que les fichiers créés par ssg5 contiennent des informations non indispensables et qu'ils peuvent être facilement compressés.

Une minification a minima

La minification d'un fichier est l'opération visant à éliminer de celui-ci tous les caractères non indispensables. Comme indiqué précédemment, les commentaires et les caractères blancs (espaces, tabulations, sauts de ligne) peuvent être supprimés d'un fichier html, css ou xml sans nuire à l'interprétation de celui-ci par un navigateur web.

Pour effectuer cette opération, deux options s'offrent à nous : utiliser un logiciel dédié à cette tâche ou créer un script basé sur des commandes de base d'un système de type Unix. Dans un objectif de garder les étapes de déploiement les plus simples et les plus rapides possibles, c'est la deuxième option qui est retenue.

Pour minifier un fichier html, on enlèvera les lignes vides, les espaces et tabulations de début et de fin de ligne et les commentaires présents dans le code. Pour cela, on pourra utiliser la commande suivante :

sed -i 's/<\!\-\-.*\-\->//g;s/^\s*//g;s/\s*$//g;/^$/d' file

Le même traitement sera appliqué aux fichiers xml, ceux-ci étant basés sur un système de balise proche de celui des fichiers html.

Pour minifier un fichier css, on enlèvera les commentaires et tous les caractères blancs, à l'exception de ceux qui influencent la mise en page du document. On pourra également utiliser une commande sed :

sed -i 's|\/\*.*\*\/||g;:a;N;$!ba;s/\n/ /g;s/\([^a-z0-9]\)\s*/\1/g;s/\s*\([^a-z0-9]\)/\1/g' file

Les lecteurs attentifs auront vu que les commentaires supprimés ici correspondent uniquement aux commentaires tenant sur une ligne. Les commentaires multilignes seront conservés, mais nous partons du principe que les personnes utilisant ssg5 comme générateur de site statique ne créerons pas de tels commentaires.

Seuls les fichiers d'extension html, xml ou css seront minifiés. Les autres extensions étant moins courantes pour des sites web statiques, elles seront ignorées.

Pourquoi compresser les pages d'un site statique ?

Pour servir les pages web le plus rapidement possible, les serveurs web compressent à la volée les pages en fonction des données fournies par le navigateur. C'est une opération qui accroit significativement la charge du serveur web, et qui, pour être efficace, doit trouver le compromis optimal entre vitesse de compression et vitesse de distribution du fichier. En effet, compresser des données demande un temps de calcul non négligeable. Celui-ci augmente si on demande à avoir un meilleur ratio de compression, pour un gain qui sera réduit par rapport à celui déjà obtenu. La vitesse de distribution des données dépend de la vitesse de la connexion internet de l'internaute, et plus le débit est faible, plus la distribution d'une page web sera lente, surtout si celle-ci n'est pas ou peu compressée.

Pour diminuer la charge des serveurs web et pour accélérer les transferts, il est possible de compresser les pages web lors de la création du site statique. Cela présente plusieurs avantages :

Le site étant statique, le contenu des pages n'est modifié que lors de la génération du site. Cela permet de les compresser qu'une seule fois, lors de la génération du site, et non pas à chaque requête issue du navigateur.

Compression des données

Un navigateur web moderne accepte les formats de page compressée gzip et brotli ; une telle page peut être obtenue à l'aide des formats gzip, zopfli et brotli. Le format gzip peut être obtenu avec les commandes gzip et pigz, zopfli avec pigz et brotli avec brotli.

Le format gzip est le plus rapide à produire, c'est également celui qui possède la compatibilité la plus large. Le format zopfli conserve la même compatibilité que celle du format gzip, mais est beaucoup plus lent à produire pour un gain assez limité dans l'essentiel des cas. Le format brotli n'est accepté que par les navigateurs les plus récents depuis 2017 environ. Il est en revanche assez lent à produire pour un gain assez faible, et n'est pas compatible avec le format gzip.

Dans un souci de simplicité et de rapidité de génération du site statique, une seule compression sera effectuée. Celle retenue sera donc celle ayant la meilleure compatibilité. Le gain en taille apporté par zopfli par rapport à gzip ne justifie pas le temps de calcul significativement supérieur nécessaire à la compression. La solution retenue sera donc gzip, avec la meilleure compression possible, uniquement pour les fichiers de plus de 300 octets :

test "$(stat -c %s file)" -ge 300 && gzip -9 < file > file.gz

Cette valeur a été choisie arbitrairement, en pensant au fait que la compression d'un fichier extrêmement petit, de l'ordre de quelques dizaines d'octets, augmente sa taille au lieu de la réduire.

smc, un utilitaire de minification et de compression pour les sites statiques

smc (static minification and compression) est l'utilitaire créé pour automatiser les étapes de minification et de compression discutées précédemment. C'est un court script compatible POSIX, traitant les fichiers html, xml, css, js et svg. Il n'a pas de dépendance particulière, si ce n'est les utilitaires de base comme sed, find et gzip. Il peut donc être exécuté sur toute machine de type Unix.

Ce script attend deux arguments :

Le script est librement téléchargeable :

wget https://www.dioptre.fr/bin/smc

On le rend alors exécutable :

chmod +x smc

On exécute alors le script sur le site :

smc src dst

Le répertoire de destination peut alors être téléversé sur le serveur web fournissant le site en question.

Annexe : Configuration du serveur web

Pour indiquer à un serveur web qu'il doit fournir un contenu préalablement compressé et pas compresser les pages à la volée, il faut modifier sa configuration courante. Ce site étant hébergé sur un serveur apache mutualisé, le fichier à modifier sera le fichier .htaccess présent à la racine du site web.

Dans ce fichier, il faudra alors détecter si le navigateur demandant la page accepte la compression gzip, et si oui, il faut lui donner la page précédemment compressée si elle existe :

RewriteCond "%{HTTP:Accept-encoding}" "gzip"
RewriteCond "%{REQUEST_FILENAME}\.gz" -s
RewriteRule "^(.*)\.(html|css|js|svg|xml)" "$1\.$2\.gz" [QSA]

Ensuite, il faut s'assurer que le serveur ne va pas compresser le contenu déjà compressé. On définit pour cela de nouveaux types de fichier, en lien avec les extensions traitées par smc :

RewriteRule "\.html\.gz$" "-" [T=text/html,E=no-gzip:1]
RewriteRule "\.css\.gz$" "-" [T=text/css,E=no-gzip:1]
RewriteRule "\.js\.gz$"  "-" [T=text/javascript,E=no-gzip:1]
RewriteRule "\.svg\.gz$"  "-" [T=image/svg+xml,E=no-gzip:1]
RewriteRule "\.xml\.gz$"  "-" [T=application/xml,E=no-gzip:1]

Enfin, il faut indiquer au navigateur que le fichier est compressé et forcer les mandataires à mettre en cache les fichiers compressés ou non à part :

<FilesMatch "(\.html\.gz|\.css\.gz|\.js\.gz|\.svg\.gz|\.xml\.gz)$">
    Header append Content-Encoding gzip
    Header append Vary Accept-Encoding
</FilesMatch>

Pour plus de détails, on pourra se reporter à la documentation d'apache.