Nginx gère les images au format Webp

Article publié, le et modifié le
5 minute(s) de lecture

Cet article contient 1006 mots.
Source brute de l'article : MD

Description

Ici, il n’est pas question de demander au serveur web nginx de modifier/créer à la volée des images au format Webp.

Pour ceux qui ne savent pas ce qu’est le format WebP, sachez que c’est un conteneur d’image matricielle, développé par… Google. Il permet de faire d’obtenir des images plus légères, qu’elles ne le seraient au format Jpeg. cf: la section Documentation ci-dessous !

Installation

Bref, cela nécessite d’installer sur votre système d’exploitation la bibliothèque nécessaire :

  • sous Linux : le paquet webp
  • sous OpenBSD : le paquet libwebp

Info

Utilisation

Pour transformer une image jpg, png, voire tiff au format, il suffit d’appeler la bibliothèque cwebp, très simplement :

cwebp -m 0 -mt "${image}" -o "${image}.webp"

Quant aux images gif, elles sont converties grâce à la bibliothèque gif2wepb :

gif2webp -m 0 -mt "${image}" -o "${image}.webp"

Veuillez lire le manpage correspondant pour connaître les différentes options de la bibliothèque :

  • $ man cwebp
  • $ man gif2webp

Voici le code que j’utilise personnellement :

_webp() {
	if [ ! -f "${file}.webp" ]; then
		case "$(file -b "${file}")" in
			'GIF'*)
				gif2webp -m 0 -mt "${file}" -o "${file}.webp"
			;;
			'JPEG'|'PNG'|'TIFF'*)
				cwebp -exact -lossless -m 0 -mt -progress "${file}" -o "${file}.webp"
			;;
		esac			
	fi;
}

Que fait ce code ?

Dans les faits, il teste :

  1. l’existence du fichier ayant l’extension de fichier .webp
  2. puis détermine le type du fichier et appelle la bonne bibliothèque selon le format détecté.

Par soucis de simplicité et de lecture, il génére une image au format webp, portant l’extension .webp, ajouté à son nom de fichier originel, tel que image.jpg.webp, pour l’exemple.
Tu verras, toi mon lecteur, que cela nous facilite la configuration de nginx, par la suite.

Ensuite, je parcoure un répertoire d’image par le biais de la fonction find, qui appelle la fonction _webp déclarée ci-dessus, tel que :

find . -type f -a \( \
		-name "*.gif" -o -name '*.jpg' -o -name '*.jpeg' -o -name '*.png' -o -name '*.tiff' \
		\) | while read -r file; do _webp; done

Voici le script shell que j’utilise :

Fichier : webp.bash

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#!/bin/bash
#set -x
clear
########################################################################
###
##
#
# Author: Stéphane HUC
# mail: devs@stephane-huc.net
# gpg:fingerprint: CE2C CF7C AB68 0329 0D20  5F49 6135 D440 4D44 BD58
#
# License: Public Domain
#
# Git:
#
# Date: 2020/10/03
#
##
###
########################################################################
##
# Convert to webp images
##
########################################################################

#ROOT="$(dirname "$(readlink -f -- "$0")")"

########################################################################

_webp() {
	if [ ! -f "${file}.webp" ]; then
		case "$(file -b "${file}")" in
			'GIF'*)
				gif2webp -m 0 -mt "${file}" -o "${file}.webp"
			;;
			'JPEG'|'PNG'|'TIFF'*)
				cwebp -exact -lossless -m 0 -mt -progress "${file}" -o "${file}.webp"
			;;
		esac			
	fi;
}

main() {
	find . -type f -a \( \
		-name "*.gif" -o -name '*.jpg' -o -name '*.jpeg' -o -name '*.png' -o -name '*.tiff' \
		\) | while read -r file; do _webp; done
}

########################################################################

main

Celui-ci est aisément modifiable pour l’utiliser sous tout autre shell.


De deux manières l’une, j’utilise ce script soit en l’appelant individuellement, soit par le biais de mon script de déploiement de mes fichiers vers le serveur web.

Ainsi, en sus des images aux formats originels, j’y dépose celles au format webp. ;-)

Configuration

Modifions la configuration de nginx, afin de lui signifier que quand il est demandé des images au format jpeg|gif|png|tiff, il essaye de diffuser celles au format webp, si elles existent.


⇒ Dans le contexte http du serveur, ajoutons une map afin de déclarer une variable $webp_suffix qui nous permettra de reconnaître une image ayant l’extension .webp.

map $http_accept $webp_suffix {
    webp_suffix "";
    "~*webp" ".webp";
}

⇒ Le script suivant est à inclure dans le contexte de la déclaration server de votre configuration d’hôte virtuel.

Fichier : /etc/nginx/conf.d/images-webp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
location ~ /*.(jpe?g|gif|png|tiff)$ {

    access_log        off;

    add_header Cache-Control "public, must-revalidate, proxy-revalidate";
    add_header Pragma public;
    add_header Vary "Accept-Encoding";    

    expires           max;

    log_not_found off;

    try_files $uri$webp_suffix $uri =404;    

}

location ~ /*.(gif|jpe?g|png|tiff).webp {

    access_log        off;

    add_header Cache-Control "public, must-revalidate, proxy-revalidate";
    add_header Content-Type image/webp;
    add_header Pragma public;
    add_header Vary "Accept-Encoding";

    default_type image/webp;

    expires           max;

	# normalement, non nécessaire car déclaré dans les types mimes reconnus par nginx 
    types { 
		image/webp webp; 
	}

}                                                                 

Ce que fait cette configuration ?

  1. Lorsqu’un appel est fait vers une image, au format sus-mentionné :
    • aucune inscription au journal n’est faite
    • envoie des entêtes HTTP nécessaires pour une bonne “publication” par le serveur vers le client.
    • essaie d’envoyer l’image portant l’extension .webp, suffixé au nom de l’image appelée, sinon retourne logiquement une erreur 404.
      remarque l’utilisation de la variable $webp_suffix à la ligne 13.
  2. L’appel à une image portant l’extension .webp :
    • n’est pas journalisé
    • envoie les entêtes HTTP nécessaires
    • définit correctement le bon type mime.

Et, voilà !!!

Reste plus qu’à tester votre configuration avec nginx et redémarrer le service correspondant - par exemple, pour OpenBSD :

# nginx -t
# rcctl restart nginx

HTML

Pour finir, modifiez votre code html à-propos de la gestion des images, tel que, par exemple pour une image jpeg, à minima :

<picture>
	<source srcset="/img/{{ $img }}.jpg.webp" type="image/webp">
	<img alt="texte" src="/img/{{ $img }}.jpg" type="image/jpeg">
</picture>

Ce qui permettra aux clients web qui supportent le format webp de demander l’affichage de ce format en lieu et place…

Essai

Test avec mon Logo :

Logo
Logo

Ainsi, selon le support du client web, vous recevrez soit le format webp, sinon le fichier “source” png…

Documentation