Makina Blog
Comment compresser son code applicatif de manière efficace avec Nginx et Brotli ?
Dans cet article, nous allons mettre en place un algorithme de compression des données textuelles plus efficace, que celui utilisé habituellement, pour réduire le poids d'une page web.
Lorsque les performances, l'accessibilité ou encore la consommation énergétique d'une page web sont analysées, son poids fait généralement partie des indicateurs considérés. En effet, une page web au poids important demande plus de temps au chargement c'est à dire au téléchargement des données. Pour réduire le poids des pages web, en général l'accent est mis sur la compression des données textuelles et images. Dans cet article, nous allons mettre en place un algorithme de compression des données textuelles plus efficace que celui utilisé habituellement dans le web. Attention, cette approche ne doit pas occulter une nécessaire sobriété fonctionnelle !
Algorithme de compression Brotli
Historiquement, c'est plutôt gzip qui est utilisé pour compresser les données textuelles si bien qu'aujourd'hui l'en-tête HTTP Content-Encoding: gzip
est supportée par tous les navigateurs. Cependant, depuis quelques années (~2020), l'algorithme de compression Brotli a été stabilisé. Il offre un taux de compression et une vitesse de décompression supérieure (au prix de performances de compression dégradées - Source). Cet algorithme est désormais suffisamment mature pour être considéré en production, puisqu'il est supporté par plus de 95% des navigateurs (source). Et pour les 5% restants, pas de soucis, la négociation de contenu HTTP permet quand même d'accéder à du contenu au format gzip. Un fichier textuel compressé avec Brotli offre en général une taille inférieur de 10 à 20% par rapport à gzip.
Cependant, au vu de la jeunesse de Brotli, la mise en place nécessite un peu plus de travail que gzip.
Pré-compresser ses données - optionnel
Tout d'abord, comme la compression avec brotli est plus coûteuse qu'avec gzip, je vous recommande de pré-compresser vos données. C'est à dire de fabriquer, pour chacun de vos fichiers HTML, JS, CSS, etc. une version déjà compressée avec l'extension '.br'. Par exemple, pour du JavaScript, vous pouvez vous baser sur ce que nous avons fait dans l'intégration continue du widget 'Geotrek Rando'.
Mise en place sur un serveur Nginx containérisé
Le support de la compression Broltli sur un serveur Nginx est encore délégué à un module tiers non inclus dans l'image Docker officielle. Son code est disponible sur google/ngx_brotli.
Il faut donc fabriquer sa propre image Docker incluant ce module. Rien de bien sorcier, les instructions du dépôt officiel sont très claires, et le module Brotli est même déjà intégré dans le repo.
Je vais donc vous montrer comment fabriquer une image Nginx intégrant la compression Brotli.
Fabrication d'une image contenant le module Brotli pour Nginx
Commençons par récupérer le Dockerfile
dans un dossier de travail :
mkdir -p nginx/
curl -o nginx/Dockerfile https://raw.githubusercontent.com/nginxinc/docker-nginx/master/modules/Dockerfile
Puis fabriquons une première image Docker qui nous sert de base :
docker build nginx/ --build-arg ENABLED_MODULES="brotli" --tag "nginx-brotli-base:latest"
Modification de la configuration par défaut de l'image
Maintenant, nous allons fabriquer une deuxième image, basée sur celle-ci qui inclut aussi une modification de la configuration par défaut de Nginx afin de charger le module Brotli. J'ai choisi de faire une deuxième image et non de modifier le Dockerfile téléchargé à l'étape précédente pour ne pas avoir à maintenir un patch pour celui-ci.
Nous allons ajouter les deux lignes suivantes dans le fichier de configuration par défaut nginx.conf
:
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;
Si nous utilisons la configuration par défaut, nous nous retrouvons donc avec le fichier suivant :
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
J'ai nommé ce fichier nginx.conf
dans mon dossier de travail.
Maintenant, écrivons un Dockerfile qui se base sur l'image précédente et qui installe notre configuration modifiée :
FROM nginx-brotli-base:latest
COPY nginx.conf /etc/nginx/nginx.conf
Désormais, nous pouvons fabriquer l'image docker finale nginx-brotli
:
docker build . --tag "nginx-brotli:latest"
Ajout du support de Brotli dans ses vhosts
Maintenant que nous avons nos fichiers pré-compilés, en gzip et en Brotli pour supporter les navigateurs un peu anciens, et une image Docker pour Nginx contenant le module Brotli chargé par défaut, nous pouvons modifier notre configuration pour un serveur web afin d'indiquer à Nginx que les fichiers pré-compressés sont disponibles.
Pour cela, ajoutez les deux directives suivantes dans un bloc server
de votre configuration :
gzip_static on
brotli_static on
La directive gzip_static on
permet d'activer l'utilisation de fichiers pré-compressés avec l'extension .gz
.
La directive brotli_static on
fait la même chose, avec l'extension .br
.
Comme pour gzip, le module Brotli supporte la compression à la volée via la direction brotli on
. Cependant d'un point de vue performance ce n'est pas forcément pertinent.
Si vous activez cette option, attention car la directive gzip_proxied
n'est pas contrôlable pour Brotli, sa valeur est fixée à any
.
En conclusion
À travers cet article, nous avons vu comment fabriquer une image Nginx et la configuration associée permettant d'activer la compression Brotli. Cette optimisation peut vous permettre de réduire la taille de vos assets textuels de 10 à 20% !
Actualités en lien
Créer une application en tant que composant web avec Stencil
Mise en place dans le cadre de Geotrek, cette solution permet de se passer d'une iFrame pour afficher une application dans n'importe quel site.
Développement de Geotrek Widget financé par le Parc Naturel Régional du Haut-Jura
Geotrek Widget est un nouveau composant web permettant de valoriser une offre de contenus touristiques et de randonnées auprès des usagers du territoire.
Bien débuter avec Nginx
Vous avez longtemps été un utilisateur plus ou moins averti de Apache HTTP Server et vous voulez commencer à tester nginx ? Voici quelques règles assez simples pour partir dans la bonne direction.