29 03 | 2013

Pré-compresser des fichiers statiques avec le Serveur HTTP Apache

Written by Tanguy

Classified in : Homepage, Auto-hébergement, Debian-FR, Libre, April, À retenir

Quand on publie un site Web constitué de fichiers statiques avec le Serveur HTTP Apache, on peut réduire le débit utilisé pour servir ces fichiers en activant la compression à la volée, avec le mod_deflate. Ainsi, si le client annonce qu'il prend cela en charge, Apache compressera les fichiers avant de les lui envoyer, et le client les décompressera à la réception.

Plume

Pré-compression

L'inconvénient de cette approche, c'est que le serveur doit effectuer la compression pour chaque requête ; il est plus efficace de pré-compresser les fichiers une fois pour toute, en conservant le fichier original pour les clients qui ne prennent pas en charge la décompression :

$ ls
index.html
$ gzip < index.html > index.html.gz
$ ls
index.html index.html.gz

On peut ensuite servir ces fichiers directement en indiquant qu'ils sont compressés. Cela se fait avec le mod_mime, en déclarant un nouvel « encodage » gzip — terme désignant une encapsulation dans le langage de la norme HTTP :

LoadModule mime_module /usr/lib/apache2/modules/mod_mime.so
AddEncoding x-gzip .gz .tgz

Négociation de contenu

Cela suffit à servir des fichiers pré-compressés, mais seulement pour les clients qui les demandent explicitement, par exemple index.html.gz. Ce n'est pas très utile, on peut donc utiliser le mod_negociation pour servir automatiquement le fichier compressé en réponse à une requête normale, index.html dans ce cas. Pour activer cette fonctionnalité :

LoadModule negotiation_module /usr/lib/apache2/modules/mod_negotiation.so
Options +MultiViews

Le problème, c'est que la « négociation de contenu », qui permet à Apache de servir un fichier parmi plusieurs candidats selon la langue, le codage et la compression pris en charge par le client, ne se déclenche que si aucun fichier ne correspond exactement à la requête. Or, même si index.html.gz serait un bon candidat pour une requête sur index.html, il y a justement un fichier index.html qui correspond à cette requête, et la négociation de contenu n'entre donc pas en jeu. Il faut donc renommer le fichier original :

$ mv index.html index.html.raw
$ ls
index.html.gz index.html.raw

… et déclarer un nouveau type de (non-)compression :

AddEncoding identity .raw

Avec cela, et en redémarrant le Serveur HTTP Apache, le fichier index.html.raw sera servi aux clients qui ne prennent pas en charge la compression, et le fichier index.html.gz à ceux qui la prennent en charge.

3 comments

tuesday 09 april 2013 à 11:47 jaes said : #1

N'y aurait-il pas moyen de ne garder que des fichiers compressés et de les décompresser à la volée ?

tuesday 09 april 2013 à 12:50 Tanguy said : #2

@jaes : Peut-être, je l'ignore, mais le gain en espace disque ne me semble pas valoir la peine.

friday 05 july 2013 à 11:49 zerodeux said : #3

On peut avantageusement remplacer 'gzip < index.html > index.html.gz' par 'gzip -k index.html'.

mod_cache sait aussi mettre en cache des versions compressées (à partir de je ne sais plus quelle version), mais sur du contenu statique on se retrouve avec tous les documents en double sur son disque. C'est assez pratique et automatique mais pas forcément élégant.

Write a comment

What is the third letter of the word dlsiv? : 

Archives