HTTP/2, HTTP/3 et minification : la minification est-elle encore utile ?

HTTP/2, HTTP/3 et minification : la minification est-elle encore utile ?

HTTP/2 et HTTP/3 changent le trajet des fichiers, pas leur poids. Mesures de taille, de compilation et de bundling : ce que la minification apporte encore.

22.10.2026
17 min de lecture
Partager cet article:
HTTPMinificationCompressionPerformanceBundle

HTTP/2 a changé le voyage des fichiers, pas leur poids

Une affirmation revient sans cesse : depuis que HTTP/2 multiplexe les requêtes, il ne serait plus utile de minifier ni de regrouper les fichiers. La moitié est exacte. Le protocole a supprimé le coût des nombreuses petites requêtes. Il n’a pas retiré un seul octet d’un fichier JavaScript, et le navigateur doit toujours télécharger, décoder et compiler chacun d’eux. Ce guide sépare ce que HTTP/2 et HTTP/3 ont changé de ce qu’ils ont laissé intact. Les chiffres viennent de trois tests du 22 octobre 2026 (le jeu de données de FastMinify, un paquet de 644 modules et un test de compilation dans V8). Les RFC et la documentation des navigateurs citées au fil du texte complètent les faits. Pour le volet compression, voyez notre guide GZIP et Brotli.

HTTP/2 et HTTP/3 changent la façon dont les requêtes sont transportées, pas la taille des fichiers qu’elles contiennent.
Sur 10 bibliothèques JavaScript non minifiées, la minification retire encore environ la moitié des octets gzip et brotli.
Sur le CSS, le gain après compression tombe à environ 6 %, donc l’argument est plus faible.
Un paquet de 644 petits modules se compresse 2,4 fois moins bien que le même code réuni dans un fichier.
V8 a compilé les bibliothèques minifiées de 7 % à 37 % plus vite, soit 0,1 à 1,2 ms par bibliothèque sur un portable rapide.
Le push serveur, le sharding de domaines et le fichier unique pour tout le site sont les habitudes à abandonner.

Ce que les protocoles ont changé, et ce qu’ils ont laissé intact

HTTP/2 transporte de nombreuses requêtes sur une connexion

HTTP/2 (RFC 9113, juin 2022) transporte de nombreuses requêtes et réponses en même temps sur une seule connexion. Avec HTTP/1.1, un navigateur ouvrait en général six connexions par hôte et mettait le reste en file d’attente. Cette file explique pourquoi les équipes concaténaient les fichiers, dessinaient des sprites et répartissaient les ressources sur plusieurs noms d’hôte.

Améliorations

Le multiplexage permet à une page de demander des dizaines de fichiers sans attendre une connexion libre.
HPACK compresse les en-têtes répétés : les cookies et l’en-tête User-Agent ne sont plus envoyés en entier à chaque requête.
L’ancien arbre de priorités des flux est déprécié. La RFC 9218 le remplace par un en-tête Priority (urgence de 0 à 7, plus un indicateur incrémental).
La RFC 9113 précise que le blocage en tête de file au niveau de TCP n’est pas traité. Un paquet perdu bloque encore tous les flux de la connexion.
HTTP/3 garde la sémantique et change le transport

HTTP/3 (RFC 9114, juin 2022) garde le modèle HTTP, mais circule sur QUIC au lieu de TCP. Un paquet perdu ne bloque plus que le flux concerné, alors qu’avec HTTP/2 il bloque tous les transferts de la connexion.

Améliorations

La compression des en-têtes passe de HPACK à QPACK, conçu pour des flux qui peuvent arriver dans le désordre.
Le bénéfice dépend des pertes de paquets. Nous ne l’avons pas mesuré ici et ne promettons donc aucun gain de vitesse.
L’adoption est réelle, mais difficile à mesurer. Le Web Almanac 2024 comptait 7 % des pages d’accueil sur ordinateur et 9 % sur mobile chargées en HTTP/3 lors de son exploration. Son auteur estime la prise en charge réelle plus proche de 30 %.
Dans le même chapitre, 71 % des pages d’accueil sur ordinateur et 70 % sur mobile étaient servies en HTTP/2, et 85 % des requêtes passaient en HTTP/2 ou HTTP/3.
Ce que ni l’un ni l’autre ne touche

Les deux protocoles déplacent des octets. Aucun ne change le nombre d’octets d’un fichier, et aucun n’analyse votre code.

Améliorations

Le Content-Encoding (gzip ou brotli) fonctionne de la même façon en HTTP/1.1, HTTP/2 et HTTP/3.
Après décompression, le navigateur détient le texte complet du script. Il doit l’analyser et le compiler en entier, quel que soit le protocole qui l’a livré.
Le push serveur, censé envoyer les fichiers avant qu’ils soient demandés, est désactivé par défaut dans Chrome 106. L’équipe de Chrome cite des résultats faibles (environ 1,25 % des sites HTTP/2 l’utilisaient) et recommande 103 Early Hints.
103 Early Hints n’envoie que des indices et laisse le navigateur décider. Le Web Almanac 2024 l’a relevé sur 2,9 % des pages d’accueil sur ordinateur.
Ce que la minification fait encore gagner après compression

Nous avons utilisé le banc d’essai de minification de FastMinify (édition 2026-10). Il mesure des fichiers non minifiés de bibliothèques publiques bruts, avec gzip niveau 9 et avec brotli qualité 11. Chaque chiffre est une somme sur les fichiers d’un langage. Le JavaScript passe par Terser 5.51.2 aux réglages par défaut, le CSS par CSSO et le JSON par JSON.stringify.

Améliorations

JavaScript, 10 fichiers : 5 637 983 octets bruts et 1 142 675 en gzip. Minifiés, 1 809 323 octets bruts et 566 618 en gzip, soit 67,9 % et 50,4 % de moins.
Le même JavaScript en brotli : 899 755 octets avant et 484 012 après (46,2 % de moins).
CSS, 6 fichiers : 1 593 647 octets bruts et 1 338 588 minifiés (16,0 % de moins). En gzip, 161 522 contre 151 049 (6,5 % de moins). En brotli, 106 426 contre 99 630 (6,4 % de moins).
JSON, 6 fichiers indentés : 14 199 411 octets bruts et 7 747 070 minifiés (45,4 % de moins). Le gain est de 28,8 % en gzip et de 15,8 % en brotli.
Lisez ces chiffres comme un plafond. Le corpus est du code source non minifié, avec commentaires et indentation, et vos fichiers donneront moins s’ils sont déjà sobres.
644 modules ou un seul fichier

Nous avons téléchargé lodash-es 4.18.1, qui livre 644 modules JavaScript, minifié chaque module avec esbuild et compressé en gzip niveau 9 et en brotli qualité 11. C’est un cas extrême, car peu de pages chargent 644 modules, mais il montre le mécanisme.

Améliorations

Les 644 modules minifiés pèsent 189 745 octets. Compressés un par un, ils totalisent 119 525 octets en gzip et 99 805 en brotli.
Les mêmes modules minifiés réunis dans un seul fichier se compressent en 50 361 octets en gzip (58 % de moins) et 41 504 en brotli.
Regroupée et minifiée par esbuild, avec les imports résolus, la bibliothèque pèse 97 292 octets, soit 35 489 en gzip et 31 205 en brotli.
Le module médian pèse 157 octets minifié et 143 octets après gzip. Un fichier si petit a peu de répétitions internes, et la compression ne trouve presque rien.
Ces sommes ignorent les 644 requêtes elles-mêmes et le temps que met le navigateur à découvrir les imports niveau par niveau.
Le temps de compilation dans V8

Nous avons compilé cinq bibliothèques avec V8 (Node 26.4.0 sur un Apple M4 Max), une fois telles que livrées et une fois minifiées avec Terser. Le test utilise new vm.Script sur une source qui change à chaque passage, pour éviter le cache de compilation. Chaque chiffre est la médiane de 30 passages, puis la médiane de cinq séries.

Améliorations

lodash : 533 Kio livrés et 70 Kio minifiés. Compilation en 1,9 ms contre 1,2 ms.
moment.js : 179 Kio et 61 Kio. 1,1 ms contre 0,8 ms.
jQuery 4.0.0 : 250 Kio et 77 Kio. 1,3 ms contre 1,2 ms.
d3 : 573 Kio et 272 Kio. 5,7 ms contre 4,9 ms.
react-dom, build de développement : 1 155 Kio et 378 Kio. 6,0 ms contre 4,8 ms.
Il s’agit de la compilation de premier niveau, sur une machine rapide. Les téléphones sont plus lents et nous n’en avons pas testé. L’équipe de V8 écrivait en 2019 que V8 analyse, sur la plupart des connexions, plus vite que le fichier ne se télécharge. La taille transférée reste donc le levier principal.

Ce qu’il faut garder et ce qu’il faut abandonner en 2026

À garder

Ces étapes sont rentables avec tous les protocoles.

Minifiez le JavaScript, le CSS, le HTML et le JSON avant la compression, avec le minificateur JavaScript, le minificateur CSS, le minificateur HTML et le minificateur JSON.
Servez du brotli aux clients qui l’acceptent et du gzip aux autres, comme décrit dans le guide GZIP et Brotli.
Regroupez en quelques fichiers par route, séparez le code des dépendances du code applicatif et retirez le code que personne n’appelle (voir tree shaking et minification).
Mettez un hash de contenu dans chaque nom de fichier et mettez en cache avec un max-age long et la directive immutable.
Intégrez le CSS critique dans la page et chargez le reste sans bloquer le rendu, comme dans le guide du CSS critique.
Envoyez 103 Early Hints ou un lien preload pour les quelques fichiers dont le premier rendu a besoin.
Les habitudes HTTP/1.1 à abandonner

Chacune avait un sens avec six connexions par hôte. Certaines coûtent maintenant quelque chose.

Répartir les ressources sur plusieurs noms d’hôte (sharding de domaines).
Compter sur le push serveur.
Dessiner un sprite uniquement pour réduire le nombre de requêtes. Les requêtes sont peu coûteuses aujourd’hui, et une icône modifiée invalide toute la planche.
Concaténer tous les scripts du site dans un seul fichier.
Intégrer des fichiers en data URI Base64 pour éviter une requête.

Vérifier ce que votre serveur envoie vraiment

Quel protocole a servi la page

Deux vérifications rapides donnent la réponse, et une troisième explique pourquoi une première visite affiche souvent h2.

Dans les DevTools de Chrome, ouvrez le panneau Network, faites un clic droit sur l’en-tête des colonnes et activez Protocol. La colonne affiche http/1.1, h2 ou h3 pour chaque requête.
Avec curl, demandez les en-têtes d’un fichier et lisez la première ligne. HTTP/2 200 indique que la connexion utilisait HTTP/2.
Un serveur annonce HTTP/3 avec un en-tête alt-svc. Le navigateur essaie alors HTTP/3 sur une connexion ultérieure, si bien que la première requête d’une visite passe souvent en h2.
Le 22 octobre 2026, fastminify.com a répondu à une requête curl en HTTP/2 et annoncé HTTP/3 dans son en-tête alt-svc. Notre version de curl ne gère pas HTTP/3, nous n’avons donc pu lire que l’annonce.
Si la réponse est compressée, et comment

L’encodage dépend de l’en-tête que le client envoie : testez avec celui d’un navigateur.

Demandez le fichier une fois par encodage qui vous intéresse, puis avec l’en-tête complet d’un navigateur, et lisez content-encoding à chaque fois.
Un serveur peut répondre gzip quand le client propose gzip et br. Comparez ce qui revient pour br seul et pour l’en-tête complet.
Vérifiez que vary: Accept-Encoding est présent, pour qu’un cache ne serve pas un corps brotli à un client qui ne sait pas le lire.
Comparez les octets transférés avec la taille décodée. La section de code plus bas donne les commandes curl.

Cinq erreurs qui survivent au passage à HTTP/2

Abandonner la minification parce que le protocole est moderne

Passer à HTTP/2 ou HTTP/3 n’est pas une raison de livrer du code lisible. Le protocole ne décide pas de ce qu’il y a dans le fichier.

Retirer l’étape de minification du build après le passage du CDN à HTTP/2.
Envoyer commentaires, indentation et noms longs en production parce que la compression s’en chargera.
Tester seulement sur une connexion de bureau rapide, où les octets en trop restent invisibles.
Sans minification, la taille gzip de nos 10 fichiers JavaScript double, de 566 618 à 1 142 675 octets.
Gardez l’étape de minification et mesurez son effet après compression, pas avant.
Servir des centaines de modules en production

Les modules natifs et HTTP/2 permettent de servir les fichiers source tels quels. L’équipe de V8 recommande toujours de regrouper pour la production, et de ne livrer sans bundle que de petites applications de moins de 100 modules environ.

Livrer en production un arbre de dépendances non regroupé.
Compter les requêtes dans le panneau Network et conclure que tout va bien parce que le multiplexage les traite en parallèle.
Oublier que les imports sont découverts niveau par niveau, si bien qu’un arbre profond ajoute des allers-retours.
Dans notre test lodash-es, compresser chaque module séparément donne 119 525 octets là où un seul fichier en donne 50 361.
Regroupez par route ou par fonctionnalité en une poignée de fichiers, et ajoutez un indice modulepreload pour les chunks critiques.
Regrouper tout le site dans un seul fichier

L’excès inverse est aussi courant. Un seul bundle pour toutes les pages signifie que chaque déploiement invalide tout le cache et que chaque page télécharge du code qu’elle n’exécute jamais.

Un unique main.js pour toutes les routes.
Aucun hash de contenu dans les noms de fichiers, donc aucune mise en cache longue possible.
Le code des dépendances mêlé au code applicatif, si bien qu’un correctif d’une ligne fait télécharger de nouveau un framework.
Le guide des modules de v8.dev note que des fichiers non regroupés peuvent charger plus vite aux visites suivantes, quand le cache est chaud.
Séparez le code des dépendances du code applicatif, nommez les fichiers par hash de contenu et servez-les avec un max-age long et immutable.
Garder les contournements de HTTP/1.1

Plusieurs habitudes n’avaient de sens qu’avec six connexions par hôte. Notre guide Base64 détaille le surcoût des data URI.

Répartir les ressources sur des hôtes cdn1, cdn2 et cdn3. Cela abandonne la connexion unique sur laquelle repose le multiplexage et ajoute du DNS et des poignées de main.
Compter sur le push serveur HTTP/2, que Chrome ne prend plus en charge par défaut depuis la version 106.
Intégrer des images en data URI Base64, ce qui les alourdit d’environ 33 % et les rend impossibles à mettre en cache séparément de la page.
Servez les ressources depuis un seul hôte, utilisez 103 Early Hints ou un lien preload pour les fichiers critiques et gardez les images en fichiers.
Attendre de HTTP/3 qu’il règle une page lourde

HTTP/3 améliore la reprise d’une connexion après une perte de paquets. Il ne réduit pas la page.

Activer HTTP/3 sur le CDN et laisser de côté le travail de performance.
Attendre un Largest Contentful Paint plus court alors que la cause est un script de 1 Mo.
Vérifier seulement que la colonne du protocole affiche h3.
Considérez HTTP/3 comme une amélioration gratuite pour les réseaux instables, et gardez votre budget d’octets.

Quatre affirmations sur HTTP/2, HTTP/3 et le poids des fichiers

HTTP/2 rend la minification inutile

L’affirmation traite un transport plus rapide comme s’il réduisait la charge utile.

Faux. Sur nos 10 fichiers JavaScript, la minification a retiré 50,4 % des octets gzip et 46,2 % des octets brotli. HTTP/2 ne change aucun de ces octets.
Gzip et brotli font déjà le travail de la minification

Compression et minification se recoupent, mais elles agissent sur des choses différentes. La compression retire la répétition. La minification retire ce dont le programme n’a jamais eu besoin.

En partie vrai pour le CSS, pas pour le JavaScript. Gzip seul ramène notre JavaScript à 20 % de sa taille. La minification divise ensuite le reste par deux. Sur le CSS, la seconde étape vaut 6,5 %.
Avec HTTP/2, il ne faut jamais regrouper

Le multiplexage a levé la limite de requêtes parallèles, pas les autres coûts d’un fichier.

Surtout faux. L’équipe de V8 recommande toujours de regrouper pour la production. Notre test de 644 modules paie 2,4 fois plus d’octets gzip que le même code dans un fichier. Sous 100 modules environ, livrer sans bundle est acceptable.
HTTP/3 rendra rapide une page lente

HTTP/3 corrige un problème réseau, la perte de paquets sur une connexion partagée.

Il ne change ni le nombre d’octets ni le temps de compilation. Il aide surtout là où des paquets se perdent. Mesurez sur vos pages avant d’espérer un gain.

Minifier et mesurer avec FastMinify

Minifier, puis comparer

Le minificateur JavaScript, le minificateur CSS, le minificateur JSON et le minificateur HTML fonctionnent dans votre navigateur et affichent la taille d’origine et la taille de sortie.

1

Collez ou déposez le fichier

Collez la source dans le volet d’entrée ou déposez un fichier. Pour le JavaScript, choisissez le niveau de compression (conservateur, normal ou agressif).

2

Lisez le panneau Compression

Le panneau affiche la taille d’origine, la taille de sortie et le pourcentage gagné. Ce sont des tailles non compressées. Comparez-les aux chiffres bruts de cet article, pas à ce qui voyage.

3

Vérifiez l’option console

Le minificateur JavaScript retire par défaut les appels à console et les instructions debugger (options « Supprimer Console » et « Supprimer Debugger »). Désactivez-les si votre code en dépend.

Réunir plusieurs fichiers avant de minifier

Les pages des minificateurs JavaScript, CSS, HTML, XML, SVG et SQL ont un bouton « Concaténation de fichiers ». Il réunit les fichiers choisis puis minifie le résultat.

1

Ouvrez la concaténation de fichiers

Sélectionnez « Concaténation de fichiers » sur la page du minificateur et ajoutez vos fichiers. Glissez-les pour les placer dans l’ordre d’exécution voulu.

2

Concaténez et minifiez

Lancez « Concaténer et minifier ». Pour le JavaScript, l’outil joint les fichiers par un point-virgule sur sa propre ligne, afin qu’un fichier n’avale pas le suivant, puis minifie l’ensemble. Il ne résout pas les imports : pour un vrai graphe de dépendances, utilisez votre bundler (voir minificateurs en ligne et outils de build).

Reproduire les mesures sur vos propres fichiers

Vérifier le protocole et l’encodage avec curl

curl -I envoie une requête HEAD, et quelques serveurs y répondent autrement qu’à un GET. Remplacez l’URL par celle d’un de vos fichiers.

Exemple de base

# La première ligne indique HTTP/2 ou HTTP/3 curl -sI https://example.com/app.js | head -n 1 # HTTP/3 est-il annoncé ? Cherchez un en-tête alt-svc curl -sI https://example.com/app.js | grep -i alt-svc # Encodage choisi par le serveur : br seul, puis l’en-tête d’un navigateur curl -sI -H 'Accept-Encoding: br' https://example.com/app.js | grep -i content-encoding curl -sI -H 'Accept-Encoding: gzip, deflate, br, zstd' https://example.com/app.js | grep -i content-encoding # Octets transférés, puis octets décodés curl -s -H 'Accept-Encoding: gzip' -o /dev/null -w '%{size_download}\n' https://example.com/app.js curl -s --compressed https://example.com/app.js | wc -c
Mesurer les tailles brute, gzip et brotli avec Node

Enregistrez le script sous le nom size.mjs. Il utilise gzip niveau 9 et brotli qualité 11, les réglages du banc d’essai.

Exemple de base

import { readFileSync } from 'node:fs' import { gzipSync, brotliCompressSync, constants } from 'node:zlib' const file = process.argv[2] const buf = readFileSync(file) const gzip = gzipSync(buf, { level: 9 }).length const brotli = brotliCompressSync(buf, { params: { [constants.BROTLI_PARAM_QUALITY]: 11, [constants.BROTLI_PARAM_SIZE_HINT]: buf.length, }, }).length console.log(`${file}: raw ${buf.length}, gzip ${gzip}, brotli ${brotli}`)

Utilisation

node size.mjs dist/app.js node size.mjs dist/app.min.js
Comparer de nombreux fichiers à un seul

Ceci mesure seulement la compression. Réunir ainsi des modules ES ne donne pas un script qui fonctionne : servez-vous-en sur un dossier pour voir le coût des fichiers minuscules.

Exemple de base

import { readdirSync, readFileSync } from 'node:fs' import { join } from 'node:path' import { gzipSync } from 'node:zlib' const dir = process.argv[2] const files = readdirSync(dir) .filter((name) => name.endsWith('.js')) .map((name) => readFileSync(join(dir, name))) const oneByOne = files.reduce((sum, buf) => sum + gzipSync(buf, { level: 9 }).length, 0) const asOneFile = gzipSync(Buffer.concat(files), { level: 9 }).length console.log(files.length, 'files', { oneByOne, asOneFile })
Mesurer le temps de compilation dans V8

Le script compile un script classique sans l’exécuter. new Script n’accepte pas les modules ES avec import ou export.

Exemple de base

import { readFileSync } from 'node:fs' import { Script } from 'node:vm' const source = readFileSync(process.argv[2], 'utf8') const times = [] for (let i = 0; i < 33; i++) { // un commentaire final unique contourne le cache de compilation const start = performance.now() new Script(`${source}\n//run${i}`) times.push(performance.now() - start) } times.splice(0, 3) times.sort((a, b) => a - b) console.log(`median ${times[Math.floor(times.length / 2)].toFixed(2)} ms`)

Continuez à minifier et abandonnez les habitudes HTTP/1.1

HTTP/2 et HTTP/3 ont rendu les petites requêtes peu coûteuses. Ils n’ont pas rendu les gros fichiers petits. La minification divise encore par deux la taille compressée d’un JavaScript non minifié, retire quelques pour cent au CSS et réduit le travail de compilation. Ce qui a perdu sa valeur, c’est la boîte à outils HTTP/1.1 : noms d’hôte multipliés, push et bundles géants. Minifiez, compressez en brotli, regroupez avec mesure et jugez le résultat aux octets qui voyagent.

Continuez à minifier le JavaScript, le CSS, le HTML et le JSON avant la compression.
Servez du brotli avec un repli gzip, et testez ce que votre serveur choisit pour l’en-tête d’un navigateur.
Réunissez le code en une poignée de fichiers mis en cache par route, ni un seul fichier ni des centaines.
Abandonnez le sharding de domaines et le push serveur, et utilisez 103 Early Hints ou preload pour les fichiers critiques.
Lisez les gains après compression et sur le réseau, et testez sur un téléphone lent avant d’annoncer un gain de vitesse.
Partager cet article
Partager cet article: