Activer la compression sur les Pages Perso

Les Pages Perso Chez Free

Par Al, le , dans Créer ses pages perso. / Dernière modification : le par Al.
Tags : Apache, PHP, Tutoriaux

Quelques trucs et astuces pour disposer des avantages de la compression des pages et fichiers textes (html, css, javascript, xml…) sur les pages perso de Free.

Généralités

Une portion importante des données transitant sur le réseau lors de la visite d'un site internet est constituée de simples fichiers textes : HTML, Javascript, CSS, XML, JSON, OpenOffice.org, Libre Office, Microsoft® Office® (Excel®, Word®, PowerPoint®), etc. Mis côte à côte ils peuvent représenter un poids non négligeable. C’est particulièrement vrai avec les bibliothèques Javascript récentes. Compresser ces données permet de réduire le temps de latence entre la requête par le navigateur et l'affichage de la page reçue depuis le serveur. Les gains sont compris entre 50% et 70% du poids des fichiers.

La première interrogation - dans le monde impitoyable de la création web et des guerres entre navigateurs modernes et antiques - concerne le support de cette fonctionnalité. Or, ici, bonne nouvelle : on peut considérer que la totalité des navigateurs supportent la décompression des pages avec HTTP/1.1 : Netscape depuis 4.06, Microsoft Internet Explorer depuis 4.0 (avec quelques petits bugs jusqu'aux versions 5.0 et 6.0 comprises), Opera depuis 5.12, Firefox toutes versions, Google Chrome toutes versions, Safari toutes versions. De plus, il incombe aux navigateurs d'envoyer un en-tête HTTP indiquant les types de pages compressées supportées. Si cet en-tête ne figure pas dans ceux reçus par le serveur, il lui suffit de ne pas activer la compression.

De manière générale, les pages perso hébergées par Free ne disposent pas de la compression des contenu web à la volée, car elles sont hébergées sur une architecture fortement mutualisée disposant d'une version de Apache et de PHP propre, entièrement développée par Free pour satisfaire les besoins d'une telle infrastructure. Dans cet environnement où les abus sont peu tolérés, voici quelques unes des bonnes pratiques à mettre en place si l'on souhaite tout de même disposer des avantages de la compression des contenus de vos fichiers textes et ainsi, améliorer significativement les temps de chargement de vos pages.

Toutefois, la compression seule des fichiers textes ne fait pas tout. Il importe également de prendre soin de n'envoyer au client que ce dont il a besoin. Il faut donc supprimer les règles CSS superflues ; minifier (réduire les caractères et les retours à la ligne superflus) le code des fichiers Javascripts, CSS, HTML, XML… et fusionner les fichiers CSS et Javascripts lorsque cela est possible, en conservant éventuellement une copie de travail non-minifiée ; compresser correctement les fichiers images afin de ne pas envoyer les miniatures incluses ou les méta-données EXIF (totalement superflues pour les navigateurs).

Enfin, la compression de certaines ressources est à proscrire car elle augmente la taille de celles-ci : les fichiers images, les fichiers PDF ou Flash (.swf et .flv), les fichiers en formats audio et vidéos pré-compressés (.ogg, .mp3, .mp4, .divx, .mpg, .avi, etc.), certains documents de présentations Libre/OpenOffice (Impress) et les fichiers dont le poids est inférieurs à 100 octets environs.

La compression par des scripts PHP

La compression par des scripts PHP est très simple à mettre en œuvre. Contrairement à ce qui est répandu sur le Web, elle ne doit cependant pas être utilisée pour la compression des fichiers « statiques » que représentent les bibliothèques et fichiers Javascripts, les feuilles de styles CSS, les pages HTML statiques, les fichiers textes, XML, etc. pour lesquels la pré-compression par GZip des fichiers est plus appropriée (moins gourmande en ressources serveur ; voir ci-après). Le résultat de la compression PHP n'étant jamais mis en cache par le serveur, il faut réserver cette fonction aux pages présentant du contenu généré dynamiquement.

Il suffit d'insérer ce code dans vos scripts pour compresser le contenu de la page envoyée au client. Les clients disposants du support de GZip recevront le contenu compressé ; les clients ne disposant pas du support de GZip recevront le contenu non-compressé :

<?php ob_start('ob_gzhandler');
Le reste du code php à insérer avant le doctype html (headers…)
?>
<!doctype html>
<html>
Le code HTML de votre page…
</html>
<?php ob_end_flush(); ?>

La première déclaration (ob_start('ob_gzhandler')) permet d'activer la compression de la page envoyée au client, la dernière (ob_end_flush()) permet de libérer le tampon du serveur pour lui permettre de passer à une autre tache.

Comme nous venons de le voir, il est très simple d'activer la compression des scripts PHP et, de part la grande flexibilité de programmation, de compresser à la volée tout type de fichier. Sur une infrastructure mutualisée, il est impossible de conserver le résultat de la compression PHP sur le serveur pour une réutilisation ultérieure par un autre client car il n'existe pas de système de cache côté serveur. Aussi, il est préférable de servir des fichiers pré-compressés afin de limiter les abus et ne pas saturer les serveurs, comme nous le verrons ci-dessous.

Liens utiles

La compression des fichiers statiques par pré-compression GZip

Si tout ou partie de votre site est constitué de pages et de fichiers statiques ou que vous n'êtes pas familier de la programmation en PHP, il ne sert à rien de modifier vos fichiers pour les passer à la « moulinette » PHP afin de les compresser. Il existe un moyen plus simple, et qui offre l'avantage de répondre aux requêtes de vos visiteurs encore plus rapidement qu'à travers une compression par PHP. Cette option offre par ailleurs l'immense avantage de servir le contenu de votre site même si PHP est planté (ce qui est tout de même relativement fréquent sur les pages perso).

Cette méthode peut être utilisée en complément de la précédente (en réservant la compression php à la volée au contenu dynamique) et en servant les fichiers textes « statiques » pré-compressés. Cette dernière méthode à l'avantage de ne pas inclure de risque de compromission par un script PHP mal codé (même un menu en php mal codé présente un risque !) et permet de servir plus rapidement le contenu car le serveur n'a pas besoin de compresser les fichiers avant de les envoyer au client.

Nous allons donc pré-compresser les fichiers localement, puis les télécharger sur le serveur via FTP. Il conviendra ensuite de configurer correctement le serveur pour qu'il serve les fichiers compressés aux clients le supportant et les fichiers non-compressés aux clients ne supportant pas la compression.

Vous réalisez vos pages html, vos fichiers css et Javascript en local, avec votre logiciel favori. Toutefois, il ne faut pas préciser les extensions de fichiers de vos liens internes qui disposeront d'une version compressée et d'une version non-compressée (par exemple : <link rel="stylesheet" type="text/css" href="/css/styles"/> ou <a href="/page2">), c'est le serveur qui se chargera de renvoyer le document qui correspond le mieux à la requête du client.

Une fois le site terminé, vous dupliquez l'ensemble des fichiers textes (.html, .css, .js, .json, .txt, .xml, .xsl…). Il suffit de les compresser via le terminal avec la commande gzip, selon la syntaxe : gzip nom-du-fichier.<extention>. Le fichier sera alors compressé au format GZip et renommé en nom-du-fichier.<extention>.gz.

Il est possible de réaliser cette opération en une seule commande (Unix), pour l'ensemble des fichiers du site ou d'un répertoire :

gzip -rk9 repertoire-à-traiter/

Ou pour un ensemble de fichiers html uniquement :

gzip -k9 *.html

Le serveur Apache de Free étant développé spécifiquement pour les besoins de cet hébergeur, certaines fonctions ne fonctionnent pas exactement comme sur les versions du logiciel disponibles au téléchargement depuis le site d'Apache. Il faut donc adapter les extensions de fichiers. Renommer les fichiers .html.gz en .htz, les fichiers .js.gz en .jgz, les fichiers .css.gz en .csz, etc.

Encore une fois, il est possible de traiter les fichiers en une seule commande (Unix) pour le site ou un répertoire :

find . -name "*.html.gz" -exec rename 's/\.html.gz$/\.htz/i' {} \;

find . -name "*.js.gz" -exec rename 's/\.js.gz$/\.jsz/i' {} \;

find . -name "*.css.gz" -exec rename 's/\.css.gz$/\.csz/i' {} \;

find . -name "*.xml.gz" -exec rename 's/\.xml.gz$/\.xmz/i' {} \;

Une fois l'ensemble des fichiers du site correctement compressés et modifiés, il reste à configurer le serveur pour qu'il délivre correctement les fichiers aux clients visitant le site, via un fichier .htaccess à la racine de votre site (à adapter selon vos besoins ; n'utilisez que ce qui vous est nécessaire et ajoutez -Indexes à la ligne Options s'il n'est pas déjà présent dans votre fichier) :

Options +MultiViews
AddType text/css .csz
AddType text/html .htz
AddType application/xml .xmz
AddType application/x-javascript .jgz
AddEncoding gzip .htz
AddEncoding gzip .xmz
AddEncoding gzip .jgz
AddEncoding gzip .csz

Une fois le site téléversé (fichiers compressés et non-compressés côte à côte) sur le serveur des pages perso de Free, le serveur choisira automatiquement entre les fichiers de même nom, compressés ou non, au sein d'un même répertoire et selon les demandes des utilisateurs.

Ainsi, les fichiers sont tous présents en double (une version compressée, une version non compressée pour chaque ressources textes) :

-rw-r--r--@ 1 <user>  <group>  15816 21 nov 15:50 toto.html
-rw-r--r--@ 1 <user>  <group>   5306 21 nov 15:50 toto.htz
-rw-r--r--@ 1 <user>  <group>   7154 21 nov 15:50 index.html
-rw-r--r--@ 1 <user>  <group>   2434 21 nov 15:50 index.htz
-rw-r--r--@ 1 <user>  <group>   6547 21 nov 15:50 toto-2.html
-rw-r--r--@ 1 <user>  <group>   2283 21 nov 15:50 toto-2.htz

Il est alors possible de vérifier le contenu des en-têtes HTTP envoyés par le serveur, et qui doivent être du type :

Requête du client :

GET /css/styles HTTP/1.1
Host: monsite.free.fr
Accept-Encoding: gzip

Réponse du serveur :

HTTP/1.1 200 OK
Date: Mon, 28 Nov 2011 18:56:06 GMT
Server: Apache/ProXad [Aug  9 2008 02:45:09]
Content-Location: styles.csz
Vary: negotiate,accept-charset,accept-encoding
TCN: choice
Last-Modified: Sun, 27 Nov 2011 13:44:38 GMT
ETag: "96b6956-5b8-4b2b79658bd80;4b2ceb02403c0"
Accept-Ranges: bytes
Content-Length: 1464
Connection: close
Content-Type: text/css; charset=utf-8
Content-Encoding: gzip

Problèmes connus

Il n'est pour le moment pas possible de configurer le serveur pour servir des fichiers compressés index.htz, lorsque ceux-ci sont présents à la racine d'un répertoire, au côté de fichiers index.html non-compressés. Il faudra passer par la compression à la volée par des scripts PHP, car la directive DirectoryIndex index n'est pas autorisée chez Free.

Il existe actuellement un bug avec l'option MultiViews des serveurs de Free : lorsque les noms des fichiers sont trop longs ou trop courts, le serveur ne « trouve » pas les fichiers. Il faut, dans ce cas, raccourcir ou allonger le nom de ceux-ci, ou utiliser des fichiers de type type-map (cf. ci-après).

Par ailleurs, dans certains cas, le serveur trouvera une réponse négociée (c'est-à-dire renvoyant un fichier compressé), mais ne trouvera pas son pendant non négocié. Il faut, en l'occurrence, limiter les extensions de fichiers à trois caractères (.htm au lieu de .html). Pensez à mettre à jour le fichier .htaccess en conséquence, si cela s'avère nécessaire.

Liens utiles

L'utilisation de fichiers type-map

Pour utiliser des fichiers type-map, il suffit d'ajouter cette ligne dans le fichier .htaccess de la racine de votre compte :

AddHandler type-map .var

Il est alors possible, dans ce cas, de désactiver Options -Multiview. Il est également possible de choisir une autre extension que .var (par exemple, sur ce site, c'est l'extension .io qui a été utilisée). On peut définir l'extension que l'on veut, du moment que l'on ne réutilise pas une extension déjà utilisée.

Pour chaque ressource compressée, on créé un fichier texte avec comme nom l'URI correspondante (par exemple styles.var). Ensuite on place dans ce fichier ces lignes :

URI: styles

URI: styles.css
Content-type: text/css;charset=utf-8

URI: styles.csz
Content-type: text/css;charset=utf-8
Content-encoding: gzip

Ce qui donne 3 fichiers au noms identiques, mais aux extensions différentes à cet emplacement :

/css/styles.var
/css/styles.css
/css/styles.csz

On upload l'ensemble des fichiers sur le serveur puis on pointe le fichier type-map dans les liens : <link rel="stylesheet" type="text/css" href="/css/styles.var"/> ou <a href="/page2.var">.

On peut également choisir de proposer des ressources alternatives selon les capacités des clients. Par exemple, pour un fichier SVG, il est préférable d'envoyer le fichier PNG seulement si le client ne gère par SVG ; et si, en plus, le client est un navigateur textuel, il est possible d'envoyer un version ASCII de l'image en dernier recours. Le fichier type-map sera ainsi rédigé :

URI: image

URI: image.svg
Content-type: image/svg+xml;charset=utf-8; qs=0.5

URI: image.svgz
Content-type: image/svg+xml;charset=utf-8; qs=0.8
Content-encoding: gzip

URI: image.png
Content-type: image/png; qs=0.1

URI: image.txt
Content-type: text/plain; qs=0.01

En plus de la compression, il est possible de préciser énormément de chose dans ces fichiers pour le choix des représentations retournées aux visiteurs (type, ordre de préférence des représentation, langue(s), etc.). Il est également possible de masquer le chemin réél d'une ressource avec ces fichiers, précisant un chemin vers un fichier présent sur l'espace ftp dont l'emplacement exact ne sera pas révélé. Ces options vont bien au-delà de la thématique de ce billet et je ne m'étenderai pas sur leur utilisation.

Liens et ressources utiles pour la compression