Compression dans HTTP
La compression est une méthode importante pour accroître les performances d'un site web. Pour certains documents, une réduction de la taille peut atteindre 70% ce qui permet de diminuer les besoins en bande passante. Au fil des ans, les algorithmes ont gagné en efficacité, et de nouveaux sont désormais pris en charge par les clients et les serveurs.
En pratique, les développeur·euse·s web n'ont pas besoin de mettre en œuvre des mécanismes de compression, car ceux-ci sont déjà intégrés aux navigateurs et aux serveurs ; ils doivent toutefois s'assurer que le serveur est correctement configuré. La compression s'effectue à trois niveaux différents :
- d'abord, certains formats de fichiers sont compressés avec des méthodes optimisées spécifiques,
- ensuite, une compression générale peut se produire au niveau HTTP (la ressource est transmise compressée de bout en bout),
- et enfin, la compression peut être définie au niveau de la connexion, entre deux nœuds d'une connexion HTTP.
Fichiers au format compressé
Chaque type de données contient une certaine redondance, c'est-à-dire de l'espace perdu. Si le texte peut généralement avoir jusqu'à 60% de redondance, ce taux peut être beaucoup plus élevé pour certains autres médias comme l'audio et la vidéo. Contrairement au texte, ces autres types de médias utilisent beaucoup d'espace pour stocker leurs données et le besoin d'optimiser le stockage et de récupérer de l'espace était évident très tôt. Les ingénieurs ont conçu l'algorithme de compression optimisé utilisé par les formats de fichiers conçus à cet effet. Les algorithmes de compression utilisés pour les fichiers peuvent être regroupés en deux grandes catégories :
- Compression sans perte, le cycle compression/décompression ne modifie pas les données. Les données ainsi décompressées correspondent à l'octet près à l'original.
Pour les images,
gifoupngutilisent une compression sans perte. - Compression avec pertes, le cycle de compression modifie la donnée originale de façon peu perceptible pour l'utilisateur·ice.
Les formats vidéos sur le Web sont des exemples de formats intégrant une compression avec pertes, pour les images
jpegest un format avec pertes.
Certains formats peuvent être utilisés à la fois pour une compression sans perte ou avec pertes tel que webp. L'algorithme de compression peut être configuré pour une compression plus ou moins élevée, ce qui influe sur le niveau de qualité en sortie. Afin d'optimiser les performances, il convient de compresser au maximum tout en conservant un niveau de qualité acceptable. Pour les images, selon le logiciel qui a permis sa création, il se peut que l'image ne soit pas compressée suffisamment pour le Web. Il est recommandé d'utiliser des logiciels permettant la compression au maximum. Il existe de nombreux outils spécialisés (angl.) pour cet usage.
Les algorithmes de compression avec pertes sont généralement plus performants que les algorithmes de compression sans perte.
Note : Puisque certains types de fichiers gèrent nativement la compression, il est souvent inutile de les compresser une seconde fois. En réalité, cela s'avère souvent contre-productif de par la taille induite par les données additionnelles nécessaires (lors de la compression, un dictionnaire de données est généré) le fichier en sortie est alors plus gros que celui avant compression. Veillez à ne pas utiliser les techniques suivantes pour les fichiers au format compressé.
Compression de bout en bout
La compression, de bout en bout constitue la compression permettant le plus de gain de performances pour le Web. La compression de bout en bout est définie par la compression du corps du message qui est effectuée par le serveur et ne est modifié qu'une fois arrivé à destination par le client. Les étapes lors du transport laissent la charge utile inchangée.
L'ensemble des navigateurs récents supportent la compression de bout en bout et le seul élément à échanger entre le serveur et le client est l'algorithme de compression à utiliser. Ces algorithmes sont optimisés pour le transport du texte. Dans les années 1990, les technologies de compression ont évoluées rapidement, il existe donc de nombreuses possibilités en termes d'algorithmes. Les algorithmes qu'il convient de considérer à l'heure actuelle sont : gzip, le plus utilisé et br le nouveau venu.
Pour sélectionner l'algorithme à utiliser, le navigateur et le serveur s'appuient sur la négociation du contenu. Le navigateur envoie un en-tête Accept-Encoding contenant les algorithmes qu'il prend en charge par ordre de préférence, le serveur en sélectionne un pour compresser le corps de la réponse et inclut l'algorithme utilisé dans l'en-tête Content-Encoding pour informer le navigateur de l'algorithme sélectionné. La négociation de contenu s'appuyant sur l'encodage des données le serveur doit envoyer un en-tête Vary contenant au moins Accept-Encoding en plus de l'en-tête de la réponse ; de cette manière, les caches peuvent mettre en cache les différentes représentations de la ressource.
La compression permettant un gain de performance significatif, il est conseillé de l'activer pour l'ensemble des fichiers à l'exception des fichiers audios et vidéos au format compressé.
Apache prend en charge la compression et utilise mod_deflate (angl.) ; nginx dispose de ngx_http_gzip_module (angl.) ; pour IIS, il existe l'élément <httpCompression> (angl.).
Transport du dictionnaire de compression
Les formats de compression modernes tels que compression Brotli et compression Zstandard peuvent utiliser des dictionnaires de données fréquemment utilisées pour augmenter encore la compression par rapport à la simple référence à celles présentes dans le fichier compressé. Typiquement, pour les réponses HTTP, cela utilise le dictionnaire statique prédéfini inclus dans ce format (par exemple le dictionnaire statique Brotli est disponible dans le code source (angl.)).
Transport du dictionnaire de compression permet à un·e développeur·euse de définir une ressource qui peut être utilisée comme dictionnaire pour les futures requêtes. Il peut s'agir d'un fichier de dictionnaire spécifique ou d'une ressource existante (par exemple, utiliser app.v1.js comme dictionnaire lors du téléchargement de app.v2.js). Cela améliore généralement la compression et donc le temps de chargement. Dans l'exemple app.vX.js, la majeure partie du téléchargement ne consisterait qu'en le delta entre les deux versions, et les octets communs pourraient être référencés à partir du fichier app.v1.js déjà téléchargé.
Compression saut par saut
La compression saut par saut, bien que similaire à la compression de bout en bout, diffère par un élément fondamental : la compression ne se produit pas sur la ressource sur le serveur, créant une représentation spécifique qui est ensuite transmise, mais sur le corps du message entre deux nœuds quelconques sur le chemin entre le client et le serveur. Les connexions entre les nœuds intermédiaires successifs peuvent appliquer une compression différente.
Pour ce faire, HTTP utilise un mécanisme similaire à la négociation de contenu pour la compression de bout en bout : le nœud transmettant la requête indique son intention en utilisant l'en-tête TE, et l'autre nœud choisit la méthode appropriée, l'applique et indique son choix avec l'en-tête Transfer-Encoding.
En pratique, la compression saut par saut est transparente pour le serveur et le client, et elle est rarement utilisée. Les en-têtes TE et Transfer-Encoding sont principalement utilisés pour envoyer une réponse par morceaux, ce qui permet de commencer à transmettre une ressource sans connaître sa longueur.
Il est important de noter que l'utilisation de Transfer-Encoding et de la compression au niveau des nœuds est si rare que la plupart des serveurs, comme Apache, Nginx ou IIS, n'ont pas de moyen simple de la configurer. Une telle configuration se fait généralement au niveau du proxy.