Makina Blog

Le blog Makina-corpus

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

Image
Widget
04/04/2023

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.

Voir l'article
Image
Vue détail widget Geotrek
28/03/2023

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.

Voir l'article
09/11/2015

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.

Voir l'article

Inscription à la newsletter

Nous vous avons convaincus