Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

Chapitre 420 minDébutant

Écoconception web : poids des pages, images et cache

Par Josselyn C., prof de BTS SIO. Mis à jour le .

À la fin de ce chapitre, tu sauras

  • mesurer le poids, les requêtes et la taille du DOM d'une page ;
  • supprimer les fonctionnalités inutiles avant d'optimiser ;
  • choisir le format, la taille et le chargement de chaque image ;
  • alléger polices, CSS, JavaScript et services tiers ;
  • configurer le cache HTTP et la compression sur Apache.

5 exercices corrigés1 schéma

Écoconcevoir un site web, c'est réduire ce qu'une page fait télécharger, calculer et afficher, sans rien retirer de ce qui est utile à l'utilisateur. Une page légère charge plus vite, coûte moins cher à héberger, reste utilisable sur un vieux téléphone et une connexion lente, et ne pousse personne à changer d'appareil. Ce chapitre suit l'optimisation d'une vraie page, du diagnostic au résultat : besoin, images, polices, JavaScript, services tiers, cache et compression.

Ce que pèse une page web

Quand tu ouvres une page, le navigateur télécharge d'abord le HTML, puis chaque ressource qu'il référence : feuilles de style, scripts, polices, images, vidéos, contenus de services tiers. Chaque ressource est une requête HTTP. Le poids de la page est la somme des octets transférés ; à ces deux mesures s'ajoute la taille du DOM, le nombre d'éléments que le navigateur doit construire et afficher.

Ces trois grandeurs pèsent sur les trois maillons du numérique :

MesureCe qu'elle sollicitePourquoi c'est un problème quand elle grossit
Poids transféréLe réseau, et le forfait de l'utilisateurChargement lent en 4G faible, données facturées, plus de trafic pour l'hébergeur
Nombre de requêtesLe serveur et le réseauPlus de connexions, plus de traitements côté serveur et côté services tiers
Taille du DOM et JavaScriptLe terminal : son processeur et sa mémoireUn vieux téléphone rame, l'utilisateur croit qu'il doit le changer

Le dernier point est le plus important, parce que la fabrication des terminaux domine l'empreinte du numérique (chapitre 2). Un site qui exige un appareil récent contribue à l'obsolescence des appareils ; un site léger prolonge leur vie. C'est le premier objectif du RGESN.

Le diagnostic de la page de suivi

Le fil rouge de ce chapitre est la page publique de suivi des livraisons de Sorbier Logistique, hébergée sur srv-web, le serveur Apache de la DMZ, à l'adresse suivi.sorbier.example. Un client y tape son numéro de colis et voit où en est sa livraison. Le premier relevé, sans cache, donne ceci :

Type de ressourceRequêtesPoids transféré
HTML160 Ko
CSS (un framework complet et cinq feuilles d'extensions)6210 Ko
JavaScript (jQuery, un carrousel, une carte, une fenêtre de discussion, deux outils de statistiques, des boutons de partage)381 150 Ko
Polices (deux familles, quatre graisses chacune)8380 Ko
Images (une photo d'accueil de 4 000 pixels de large, les logos des partenaires, les vignettes du carrousel)592 380 Ko
Total1124 180 Ko

Le DOM compte 1 450 éléments. Sur un smartphone de cinq ans en 4G moyenne, la page met plusieurs secondes à devenir utilisable.

Avant : 4 180 Ko, 112 requêtesImages : 2 380 KoJavaScript : 1 150 KoAprès : 690 Ko, 28 requêtessix fois plus légère, quatre fois moins de requêtesImages : 2 380 → 550 KoJavaScript : 1 150 → 85 KoPolices : 380 → 0 KoCSS : 210 → 25 KoHTML : 60 → 30 Ko
La page de suivi des livraisons avant et après l'écoconception : six fois plus légère, quatre fois moins de requêtes

Commencer par le besoin

Avant d'optimiser une ressource, demande-toi si elle doit exister. Que vient faire le visiteur ? Taper un numéro et lire un statut. Tout le reste se discute.

ÉlémentQuestionDécision
Carrousel de cinq photosQuelqu'un le regarde-t-il ? Les statistiques montrent que presque personne ne dépasse la première imageUne seule photo, plus petite
Fenêtre de discussionQuelques conversations par mois, toutes sur le même sujet (« où est mon colis ? »), auquel la page répond déjàSupprimée, remplacée par un lien vers le formulaire de contact
Carte interactive de l'entrepôtLes clients ne viennent pas à l'entrepôtUne adresse en texte et un lien vers un service de cartes
Deux outils de statistiquesIls mesurent la même choseUn seul, configuré au minimum
Boutons de partage sur les réseaux sociauxQui partage le suivi de son colis ?Supprimés

C'est la logique des critères 1.1 (utilité), 4.3 (parcours de navigation optimisé) et 4.6 (contenus porteurs d'information) du RGESN. Chaque fonctionnalité retirée, c'est du poids en moins, mais aussi du code en moins à maintenir, à mettre à jour et à sécuriser.

Les images, premier poste de poids

Les images représentaient plus de la moitié du poids. Quatre réglages suffisent souvent à les diviser par quatre.

1. Le bon format. Chaque type d'image a son format.

ContenuFormat conseilléPourquoi
PhotoAVIF ou WebP, avec un JPEG de secours si nécessaireÀ qualité égale, nettement plus légers que le JPEG ; pris en charge par tous les navigateurs actuels
Logo, icône, pictogramme, schémaSVGDu texte vectoriel : quelques kilo-octets, net à toutes les tailles
Capture d'écran avec du texte, image à aplatsPNG ou WebP sans perteLe JPEG fait baver le texte
Animation courteVidéo (MP4, WebM) plutôt que GIFUn GIF animé pèse souvent plusieurs fois plus que la même séquence en vidéo

2. La bonne taille. La photo d'accueil faisait 4 000 pixels de large pour un affichage à 800 pixels au plus, soit 1 200 pixels réels sur un écran haute densité : le navigateur téléchargeait onze fois trop de pixels. Avec les attributs srcset et sizes, il choisit lui-même le fichier adapté à l'écran (images responsives).

3. La bonne compression. Règle la qualité à l'œil, image par image : une photo d'illustration supporte une compression forte. En ligne de commande, l'outil cwebp (paquet webp sous Debian) convertit et redimensionne :

bash
# Photo redimensionnée à 1 200 pixels de large (hauteur proportionnelle), qualité 75
cwebp -q 75 -resize 1200 0 entrepot.jpg -o entrepot-1200.webp

4. Le chargement différé. Une image située plus bas dans la page n'a pas besoin d'être téléchargée avant que l'utilisateur fasse défiler : l'attribut loading="lazy" s'en charge. Ne le mets jamais sur l'image principale du haut de page, qui doit s'afficher tout de suite. Déclare toujours width et height, pour que la mise en page ne saute pas pendant le chargement (WebP, AVIF et chargement différé).

html
<!-- Image principale : formats modernes, taille adaptée, pas de chargement différé -->
<picture>
  <source type="image/avif" srcset="img/entrepot-800.avif 800w, img/entrepot-1200.avif 1200w"
          sizes="(max-width: 800px) 100vw, 800px">
  <source type="image/webp" srcset="img/entrepot-800.webp 800w, img/entrepot-1200.webp 1200w"
          sizes="(max-width: 800px) 100vw, 800px">
  <img src="img/entrepot-800.jpg" alt="Quai de chargement de l'entrepôt de Mâcon"
       width="800" height="450">
</picture>

<!-- Logo d'un partenaire, plus bas dans la page : SVG et chargement différé -->
<img src="img/partenaire-transports-roux.svg" alt="Transports Roux"
     width="160" height="48" loading="lazy">

Polices, CSS et JavaScript

Les polices. Chaque graisse d'une police est un fichier : deux familles en quatre graisses, c'est huit téléchargements avant d'afficher le texte correctement. La solution la plus sobre est la pile de polices système : le texte s'affiche avec la police déjà installée sur l'appareil, sans aucun téléchargement.

css
body {
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

Si la charte graphique impose une police, garde une seule famille, deux graisses au plus, au format WOFF2, et ajoute font-display: swap pour que le texte s'affiche tout de suite avec une police de secours (critère 4.8 du RGESN).

Le CSS. Un framework CSS complet pour une page de trois blocs, c'est 200 Ko de règles dont la plupart ne servent pas. Écris le CSS dont la page a besoin, ou configure l'outil de construction pour retirer les règles inutilisées, puis minifie le fichier.

Le JavaScript. C'est la ressource la plus coûteuse pour le terminal : il faut la télécharger, mais aussi l'analyser et l'exécuter, ce qui occupe le processeur. Trois réflexes :

  • Utiliser les éléments natifs du HTML avant une bibliothèque : <details> et <summary> pour un accordéon, <dialog> pour une fenêtre modale, <input type="date"> pour un calendrier. Ils fonctionnent sans script, au clavier et avec les lecteurs d'écran (critère 4.5 du RGESN).
  • Charger les scripts sans bloquer l'affichage, avec l'attribut defer.
  • Limiter les requêtes pendant la saisie. Si le champ de suivi interroge le serveur à chaque frappe, un numéro de 11 caractères envoie 11 requêtes. Vérifie d'abord le format côté navigateur, puis attends que l'utilisateur ait fini de taper (critères 4.9 et 4.10).
html
<label for="numero">Numéro de colis (format SL-12345678)</label>
<input id="numero" name="numero" pattern="SL-[0-9]{8}" required autocomplete="off">
js
// N'appelle la fonction qu'après 300 ms sans nouvelle frappe
function debounce(fonction, delai) {
  let minuteur;
  return (...args) => {
    clearTimeout(minuteur);
    minuteur = setTimeout(() => fonction(...args), delai);
  };
}

const champ = document.querySelector('#numero');
champ.addEventListener('input', debounce(() => {
  if (champ.checkValidity()) chercherColis(champ.value); // aucune requête si le format est faux
}, 300));

Les services tiers et les vidéos

Un service tiers est une ressource chargée depuis un autre domaine : outil de statistiques, police hébergée ailleurs, vidéo intégrée, carte, bouton de réseau social, fenêtre de discussion. Chacun ajoute des requêtes que tu ne maîtrises pas, et la plupart déposent des traceurs, ce qui impose un consentement au titre du RGPD.

  • Pèse chaque service tiers dans l'onglet Réseau, en filtrant par domaine. Le critère 4.4 du RGESN demande que l'utilisateur puisse décider de leur activation.
  • Remplace une vidéo ou une carte intégrée par une façade : une image légère avec un bouton « Lancer la vidéo » ou « Afficher la carte ». Le lecteur et ses dizaines de requêtes ne se chargent qu'au clic.
  • Préfère un outil de mesure d'audience sobre et configuré pour l'exemption de consentement, comme le permet la CNIL (mesure d'audience et RGPD).
  • Pour tes propres vidéos : pas de lecture automatique, preload="none" et une image d'aperçu (poster), une définition adaptée à la taille d'affichage, et si possible un mode « écoute seule » quand l'image n'apporte rien (critère 5.5).

Le cache et la compression, côté serveur

Le cache HTTP permet au navigateur de réutiliser une ressource déjà téléchargée. C'est l'en-tête Cache-Control, envoyé par le serveur, qui fixe la règle.

RessourceRègleEffet
Fichiers CSS et JS versionnés (site.3f9a2c1b.css, le nom change à chaque modification)public, max-age=31536000, immutableGardés un an sans jamais redemander : un nouveau contenu aura un nouveau nom
Images, policespublic, max-age=2592000Gardées trente jours
Pages HTMLno-cacheLe navigateur redemande à chaque fois, mais le serveur répond 304 Not Modified, sans renvoyer la page, si elle n'a pas changé

La compression réduit les ressources texte (HTML, CSS, JavaScript, JSON, SVG) avant leur envoi, souvent des deux tiers. Sur Debian, le module deflate d'Apache (compression gzip) est actif par défaut pour le HTML, le CSS et le JavaScript ; le module brotli, plus efficace, existe aussi. Les images AVIF, WebP ou JPEG sont déjà compressées : les recompresser ne sert à rien.

Enfin, HTTP/2 envoie toutes les ressources d'une page sur une seule connexion, et le critère 6.7 du RGESN demande de servir les ressources statiques depuis un même domaine pour en profiter. HTTP/2 n'est négocié qu'en HTTPS (les navigateurs ne le parlent que sur des adresses https://), et pas du tout avec le module MPM prefork : si Apache tourne en prefork, ce qui arrive quand le paquet libapache2-mod-php est installé, passe d'abord à PHP-FPM et au MPM event. Voici la configuration ajoutée sur srv-web :

apache
# /etc/apache2/conf-available/suivi-performance.conf
Protocols h2 http/1.1

<IfModule mod_headers.c>
    # Fichiers versionnés : un an en cache, sans revalidation
    <FilesMatch "\.[0-9a-f]{8}\.(css|js)$">
        Header set Cache-Control "public, max-age=31536000, immutable"
    </FilesMatch>
    # Images et polices : trente jours
    <FilesMatch "\.(avif|webp|jpg|svg|woff2)$">
        Header set Cache-Control "public, max-age=2592000"
    </FilesMatch>
    # Pages HTML : toujours revalider (réponse 304 si rien n'a changé)
    <FilesMatch "\.html$">
        Header set Cache-Control "no-cache"
    </FilesMatch>
</IfModule>
bash
sudo a2enmod headers http2            # modules des en-têtes et de HTTP/2
sudo a2enconf suivi-performance       # active le fragment de configuration
sudo apache2ctl configtest            # doit répondre « Syntax OK »
sudo systemctl reload apache2

# Vérifier l'en-tête de cache et la compression d'un fichier CSS
curl -sI -H "Accept-Encoding: gzip" https://suivi.sorbier.example/css/site.3f9a2c1b.css \
  | grep -i -E "cache-control|content-encoding"
text
cache-control: public, max-age=31536000, immutable
content-encoding: gzip

Le résultat

Après ces changements, la page de suivi pèse 690 Ko (contre 4 180) pour 28 requêtes (contre 112) et 610 éléments dans le DOM (contre 1 450). Elle n'a rien perdu de sa fonction : on y suit toujours son colis, plus vite. À la deuxième visite, presque tout vient du cache.

Type de ressourceRequêtesPoids transféré
HTML130 Ko
CSS125 Ko
JavaScript385 Ko
Polices00 Ko
Images23550 Ko
Total28690 Ko

Le chapitre 7 transforme ces mesures en score EcoIndex : la page passe de la note F à la note C.

Exercices

Exercice 1 sur 5 Mesurer le gain Réussi À revoir

Reprends les deux tableaux de la page de suivi.

  1. De quel pourcentage le poids transféré a-t-il baissé ? Et le nombre de requêtes ?
  2. Quel type de ressource a le plus contribué à la baisse du poids, en kilo-octets ?
  3. Le critère 6.1 du RGESN cite en exemple l'objectif de passer de 2 Mo à 1 Mo et sous les 30 requêtes par page. La page optimisée respecte-t-elle ces ordres de grandeur ?
Voir la réponseMasquer la réponse de l'exercice 1
  1. Poids : 1 − 690 / 4 180 ≈ 0,835, soit une baisse de 83,5 % (la page est environ 6 fois plus légère). Requêtes : 1 − 28 / 112 = 0,75, soit 75 % de requêtes en moins.
  2. Les images : 2 380 − 550 = 1 830 Ko gagnés. Viennent ensuite le JavaScript (1 150 − 85 = 1 065 Ko), les polices (380 Ko) et le CSS (185 Ko).
  3. Oui : 690 Ko, sous la barre de 1 Mo, et 28 requêtes, sous les 30. Pour valider le critère, l'équipe doit encore fixer ces limites, les publier dans sa déclaration d'écoconception et les respecter dans les évolutions futures.

Tu avais trouvé ?

Exercice 2 sur 5 Choisir le format Réussi À revoir

Pour chaque image du site de Sorbier, choisis le format le plus adapté.

  1. Le logo de Sorbier Logistique, deux couleurs.
  2. La photo d'un quai de chargement.
  3. Une capture d'écran de l'espace client, avec beaucoup de texte, pour l'aide en ligne.
  4. Une animation de trois secondes qui montre comment trouver son numéro de colis.
  5. Douze pictogrammes de statut (en préparation, expédié, livré…).
Voir la réponseMasquer la réponse de l'exercice 2
  1. SVG : un logo vectoriel pèse quelques kilo-octets et reste net à toutes les tailles.
  2. AVIF ou WebP, en plusieurs largeurs avec srcset, et un JPEG de secours si des navigateurs anciens doivent être pris en charge.
  3. PNG ou WebP sans perte : le JPEG rendrait le texte flou. Redimensionne la capture à sa taille d'affichage.
  4. Une vidéo courte (MP4 ou WebM), sans lecture automatique, plutôt qu'un GIF animé, bien plus lourd.
  5. SVG, idéalement regroupés dans un seul fichier de symboles ou écrits directement dans le HTML, pour éviter douze requêtes.

Tu avais trouvé ?

Exercice 3 sur 5 Trouver les erreurs Réussi À revoir

Relève les pratiques non sobres dans cet extrait, et propose une correction pour chacune.

html
<link rel="stylesheet" href="https://cdn.example.com/framework-complet.min.css">
<link rel="stylesheet" href="https://fonts.example.com/css?family=Titre:300,400,600,700">
<script src="https://cdn.example.com/jquery.min.js"></script>
<video src="video/presentation-4k.mp4" autoplay muted loop></video>
<img src="img/entrepot.jpg" loading="lazy" alt="Entrepôt">

L'image entrepot.jpg est la grande photo du haut de page et mesure 4 000 pixels de large.

Voir la réponseMasquer la réponse de l'exercice 3
  • Framework CSS complet chargé depuis un autre domaine : écrire ou extraire seulement le CSS utile, et le servir depuis le même domaine que la page (critère 6.7).
  • Police en quatre graisses depuis un service tiers : passer aux polices système, ou héberger soi-même une seule famille en WOFF2, deux graisses au plus.
  • jQuery chargé de façon bloquante, sans doute pour quelques lignes : réécrire ces lignes en JavaScript natif, et charger les scripts restants avec defer.
  • Vidéo 4K en lecture automatique et en boucle : supprimer autoplay et loop, ajouter preload="none" et une image poster, encoder dans une définition adaptée à la taille d'affichage. Se demander d'abord si cette vidéo est utile.
  • Image principale en loading="lazy" : la retirer, car l'image du haut de page doit se charger tout de suite. Ajouter width et height, servir des versions redimensionnées en AVIF ou WebP avec srcset, et un texte alternatif plus précis.

Tu avais trouvé ?

Exercice 4 sur 5 Combien de requêtes pendant la saisie ? Réussi À revoir

Un client tape au clavier le numéro SL-20261108, sans pause, en moins de 300 ms entre deux frappes.

  1. Combien de requêtes part-il vers le serveur si la recherche se lance à chaque événement input ?
  2. Et avec la fonction debounce de 300 ms du chapitre, sans le test checkValidity() ?
  3. Le client tape ensuite SL-2026 et s'arrête une seconde pour retrouver la suite, puis tape 1108. Combien de requêtes avec debounce seul ? Et avec debounce et checkValidity() ?
Voir la réponseMasquer la réponse de l'exercice 4
  1. 11 requêtes : une par caractère tapé, dont 10 pour des numéros incomplets.
  2. 1 requête : chaque frappe relance le minuteur, qui ne se déclenche que 300 ms après la dernière.
  3. Avec debounce seul : 2 requêtes, une après la pause (pour SL-2026, un numéro incomplet) et une à la fin. Avec checkValidity() en plus : 1 requête, car SL-2026 ne respecte pas le motif SL-[0-9]{8} et n'est pas envoyé.

Tu avais trouvé ?

Exercice 5 sur 5 Écrire les règles de cache Réussi À revoir

Pour chaque fichier servi par srv-web, donne la valeur de Cache-Control adaptée et justifie.

  1. index.html, la page d'accueil, modifiée plusieurs fois par mois.
  2. assets/app.8c41d2e7.js, produit par l'outil de construction.
  3. img/entrepot-1200.avif, une photo qui ne change pas.
  4. api/colis/SL-20261108, la réponse JSON qui donne le statut d'un colis.
Voir la réponseMasquer la réponse de l'exercice 5
  1. no-cache : le navigateur revalide à chaque visite et reçoit une réponse 304 sans contenu si la page n'a pas changé. Il voit tout de suite une nouvelle version.
  2. public, max-age=31536000, immutable : le nom contient une empreinte du contenu, donc un fichier modifié aura un autre nom. On peut le garder un an sans risque.
  3. public, max-age=2592000 (trente jours) : la photo change rarement ; si elle change, il faudra lui donner un nouveau nom ou accepter un délai.
  4. no-store, ou au plus une durée très courte : le statut d'un colis change et il est propre à un client. Il ne doit pas être gardé par un cache partagé (private au minimum). C'est au serveur de mettre en cache le calcul s'il est coûteux (chapitre 5).

Tu avais trouvé ?

Chapitre terminé !

Fais les 5 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Chapitre suivant : Écoconception logicielle : fonctionnalités, données et APIRevoir le sommaire du cours