Guide de la minification : CSS, JS et HTML expliqués
La minification supprime les caractères dont une machine n’a pas besoin, comme les espaces, les commentaires et les sauts de ligne, de votre source CSS, JavaScript et HTML, et réécrit les motifs verbeux en équivalents plus courts. Le comportement reste identique ; le fichier devient simplement plus petit et se charge plus vite.
Une distinction à poser d’emblée : la minification n’est pas la compression. La minification agit sur votre code source, en éliminant la redondance syntaxique. Gzip et Brotli agissent sur les octets en transit, en encodant les motifs répétés. Ils interviennent à des étapes différentes, attaquent des types de redondance différents et se cumulent l’un sur l’autre. C’est pourquoi vous devriez toujours minifier, même quand votre serveur sert déjà du Brotli. Ce guide explique précisément pourquoi.
Vous voulez compresser quelque chose tout de suite ? Allez directement au minificateur CSS, au minificateur JavaScript ou au minificateur HTML ; chacun s’exécute entièrement dans votre navigateur. Mais comprendre les mécanismes est ce qui vous permet de décider où compresser et si vous avez même besoin de le faire à la main. Nous verrons ce que fait réellement la minification, comment CSS, JS et HTML sont chacun minifiés, comment la minification se cumule avec gzip et Brotli, quand votre outil de build s’en charge déjà, et comment les source maps gardent le code minifié débogable.
Qu’est-ce que la minification (et ce qu’elle n’est pas)
La minification fait deux choses. Elle supprime les caractères qui ne portent aucun sens pour l’analyseur, et elle réécrit votre source dans une forme plus courte qui signifie exactement la même chose. Le résultat est parfaitement équivalent pour une machine et quasiment illisible pour un humain. Rien ne change dans la façon dont le code s’exécute ; seule sa surface change.
Ce dernier point est l’invariant à garder en tête pour le reste de ce guide : la minification n’édite que la surface de votre source (espaces, commentaires, noms d’identifiants, syntaxe redondante), jamais le comportement ni le résultat. C’est l’image miroir du formatage. Le formatage ajoute des espaces pour rendre le code lisible ; la minification les retire pour rendre le code petit. Les deux se situent sur le même axe « sémantiquement équivalent », mais pointent dans des directions opposées.
Les gens confondent constamment trois opérations qui se ressemblent. Ce tableau les distingue :
| Dimension | Formater (embellir) | Minifier | Compresser (gzip/Brotli) |
|---|---|---|---|
| Ce qu’elle change | Ajoute espaces, sauts de ligne, indentation | Retire espaces et commentaires, raccourcit la syntaxe | Encodage au niveau des octets des motifs répétés |
| Quelle couche | Code source | Code source | Transfert / stockage |
| Toujours du code source ? | Oui (lisible) | Oui (exécutable, difficile à lire) | Non (binaire, doit être décodé) |
| Qui le fait | Développeur / éditeur | Outil de build / minificateur | Serveur + navigateur |
| Réversible ? | Sémantiquement | Sémantiquement (comportement inchangé) | Totalement (la décompression restaure les octets) |
Formater et minifier vivent sur un même axe, celui de l’équivalence sémantique. La compression vit sur un axe totalement différent. Un fichier formaté et un fichier minifié sont tous deux des sources valides ; un fichier compressé est un blob binaire qui doit être décodé avant que quoi que ce soit puisse s’exécuter.
C’est ici qu’une idée fausse coûteuse s’installe : « mon serveur fait déjà du gzip, donc minifier ne sert à rien ». Faux, et les chiffres plus loin dans ce guide montrent pourquoi. Minification et compression éliminent des redondances différentes, donc faire l’une ne rend pas l’autre superflue. Gardez cela en tête tandis que nous parcourons chaque langage.
Il vaut la peine de réfléchir au pourquoi les octets qu’un minificateur retire existent en premier lieu. Vous écrivez des espaces, des commentaires et des noms descriptifs pour vous-même et vos coéquipiers, parce qu’ils rendent le code relisible et maintenable. La machine qui analyse votre CSS, exécute votre JavaScript ou construit votre DOM les ignore tous. La minification est l’étape qui jette le matériel réservé aux humains une fois que les humains en ont fini avec la source. C’est aussi pourquoi la minification est une préoccupation de production et jamais de développement : vous conservez la version lisible dans votre dépôt et vous expédiez la version allégée aux navigateurs. La copie lisible est la source de vérité ; la copie minifiée est un artefact de build que vous pouvez régénérer à tout moment.
Comment fonctionne la minification CSS
Le CSS est le plus doux des trois à minifier, parce que sa grammaire laisse peu de place à l’ambiguïté. Un minificateur retire les commentaires, réduit les suites d’espaces à néant, supprime le point-virgule final de chaque bloc et retire les espaces autour de {, }, : et ;. Cela élimine à soi seul la majeure partie des octets.
Le CSS autorise aussi un ensemble de réécritures par équivalence qu’aucun autre langage ne partage. Un bon minificateur les applique en toute sécurité :
- Raccourcir les couleurs :
#ffffffdevient#fff, et#ff0000se réduit àred(ou l’inverse, selon ce qui est le plus court à écrire). - Supprimer les unités sur zéro :
0pxdevient0, etmargin: 0 0 0 0devientmargin: 0. - Retirer les zéros de tête :
0.5emdevient.5em. - Fusionner les raccourcis : quatre déclarations distinctes
margin-top,margin-right,margin-bottometmargin-leftse replient en un seulmargin. - Combiner les règles : des règles adjacentes aux sélecteurs ou déclarations identiques peuvent être fusionnées, et les déclarations en double supprimées.
Chacune de ces transformations garde le rendu identique, et c’est la limite qu’un minificateur conforme ne franchit jamais. Mais le CSS est sensible à l’ordre : une règle ultérieure en écrase une antérieure via la cascade. Un minificateur sûr ne réordonnera donc pas aveuglément des règles qui pourraient changer laquelle des déclarations l’emporte. Réduire les octets est permis ; modifier la cascade ne l’est pas.
Cette contrainte est plus subtile qu’il n’y paraît. Deux déclarations qui semblent fusionnables peuvent ne pas l’être, parce que quelque chose entre elles référence la même propriété à la même spécificité. Considérez :
.btn { color: #ff0000; }
.alert .btn { color: blue; }
.btn { color: #f00; }
La première et la troisième règle partagent un sélecteur et pourraient fusionner, mais seulement si cela ne déplace pas la déclaration au-delà de la règle du milieu d’une manière qui changerait laquelle l’emporte pour un élément correspondant aux deux. Une fusion naïve qui réordonne ces règles pourrait casser la cascade. C’est le genre de cas limite qu’un moteur de qualité production comme CSSO est conçu pour raisonner, et c’est pourquoi vous ne devriez pas bricoler votre propre minificateur « supprimez les espaces » avec une regex. Les transformations semblent mécaniques, mais l’analyse de sécurité derrière elles ne l’est pas.
Notre minificateur CSS utilise le moteur CSSO pour exactement ce type de minification sans perte, et il s’exécute entièrement dans votre navigateur avec un affichage des octets économisés, pour que vous puissiez voir l’impact sur la charge utile à chaque passe. Le même outil formate aussi dans l’autre sens, vous pouvez donc prendre une feuille de style minifiée copiée sur un site en production et la redéployer en règles lisibles et indentées. Tournez-vous vers lui quand vous avez copié un extrait de CSS et voulez vérifier sa taille compressée, ou quand vous expédiez une page statique sans étape de build pour le faire à votre place.
Comment fonctionne la minification JavaScript
La minification JavaScript va bien plus loin que celle du CSS, et c’est là que se trouvent à la fois les gains et les pièges. Pour comprendre pourquoi, regardez une petite fonction avant et après Terser :
// before
function calculateTotal(items, taxRate) {
let runningTotal = 0;
for (const item of items) {
runningTotal += item.price * item.quantity;
}
return runningTotal * (1 + taxRate);
}
// after
function calculateTotal(t,a){let n=0;for(const o of t)n+=o.price*o.quantity;return n*(1+a)}
Le nom de fonction calculateTotal survit parce qu’il est exporté (ou pourrait être appelé d’ailleurs) ; les paramètres et les variables de boucle se réduisent à des lettres uniques. C’est le cœur de l’affaire, mais un minificateur JS fait plusieurs choses distinctes :
- Renommage d’identifiants (mangling) : les variables locales et les paramètres sont renommés en lettres uniques, donc
getUserPreferencesdevienta. Seules les variables locales sont renommées ; les globales et les noms exportés restent intacts par défaut, parce que les renommer casserait le code qui les référence depuis l’extérieur. - Élimination du code mort : les branches inatteignables et les variables inutilisées sont supprimées, main dans la main avec le tree-shaking au niveau du bundler.
- Pliage de constantes et compression syntaxique : les expressions sont raccourcies, donc
truedevient!0,falsedevient!1, etreturn undefined;devientreturn;.
Le point le plus précieux à savoir sur la minification JS est le piège de l’insertion automatique de point-virgule (ASI). JavaScript vous laisse omettre les points-virgules, et l’analyseur les insère pour vous selon des règles précises. Quand un minificateur supprime les sauts de ligne dont ces règles dépendent, le code peut changer de sens. L’échec classique est une instruction qui commence par ( ou [ se collant silencieusement à la ligne précédente :
const x = getValue()
[1, 2, 3].forEach(handle)
Sans points-virgules, cela s’analyse comme getValue()[1, 2, 3], soit une expression d’indexation et non deux instructions. Une fois minifié sur une seule ligne, le bug est figé. Le même danger apparaît avec une ligne commençant par (, où l’expression précédente est appelée comme une fonction. Le Terser moderne gère la plupart des cas réels avec élégance parce qu’il analyse le code en un arbre syntaxique abstrait d’abord et réémet les points-virgules là où ils sont nécessaires, plutôt que de supprimer du texte à l’aveugle. Mais une source de mauvaise qualité plus une minification agressive est une véritable source de bugs en production, et les échecs sont d’autant plus pénibles qu’ils n’apparaissent que dans le build minifié, pas en développement. La correction vous incombe : écrivez du code avec des points-virgules explicites et une syntaxe non ambiguë, et le minificateur reste sûr. Une règle de linter ou un formateur automatique qui insère les points-virgules au niveau de la source élimine entièrement le risque.
Un minificateur conforme préserve le comportement, mais seulement si l’entrée est du JavaScript valide et standard. Terser analyse l’ECMAScript ; il ne comprend ni le TypeScript ni le JSX. Ceux-ci doivent d’abord être transpilés en JS pur, sinon la minification échoue à l’étape d’analyse. Si vous collez un fichier .ts dans un minificateur JS et obtenez une erreur, voilà pourquoi.
Une question de vocabulaire revient souvent : minify contre uglify. Ils signifient en pratique la même chose. « Uglify » vient d’UglifyJS, le premier minificateur JS populaire ; Terser en est le fork moderne qui prend en charge ES2015 et au-delà. Aujourd’hui « minify » est le terme générique pour les trois langages, et « uglify » survit comme un nom plus ancien, spécifique au JS, pour le même processus.
Notre minificateur JavaScript exécute Terser dans le navigateur, où il renomme les variables locales, supprime le code mort et retire les commentaires, puis indique combien d’octets il a économisés à chaque passe.
Comment fonctionne la minification HTML
La minification HTML commence par les bases : retirer les commentaires (en conservant la déclaration <!DOCTYPE> et tout commentaire conditionnel dont vous dépendez encore), réduire les espaces entre les balises et supprimer les espaces redondants à l’intérieur des listes d’attributs. Un petit fragment en montre la forme :
<!-- nav -->
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
devient :
<ul><li><a href=/>Home</a><li><a href=/about>About</a></ul>
Le commentaire a disparu, l’indentation entre balises est réduite, les balises de fermeture facultatives </li> sont supprimées, et les valeurs d’attribut sans guillemets perdent leurs guillemets. À partir de là, un minificateur peut appliquer quelques astuces supplémentaires propres au HTML :
- Retirer les balises de fermeture facultatives : la spécification HTML autorise l’omission de
</li>,</p>,</td>et plusieurs autres, donc un minificateur peut les supprimer. - Retirer les guillemets d’attribut : quand une valeur n’a aucun espace ni caractère spécial,
class="x"devientclass=x. - Réduire les attributs booléens :
disabled="disabled"devient simplementdisabled, etchecked="checked"devientchecked. - Minifier le CSS et le JS intégrés : le contenu des blocs
<style>et<script>est minifié aussi, donc une seule passe réduit le document entier.
La limite qui compte le plus ici : en HTML, l’espace est parfois significatif. À l’intérieur de <pre> et <textarea>, chaque espace et chaque saut de ligne est rendu littéralement. Les éléments avec white-space: pre se comportent de la même façon. Et l’espace entre les éléments en ligne affecte la mise en page, puisqu’un espace entre deux balises <a> apparaît comme un écart sur la page. Une minification agressive qui aplatit cet espace peut changer l’apparence de la page. La règle empirique : après minification, vérifiez le rendu autour de pre, textarea et des frontières entre éléments en ligne avant d’expédier.
Notre minificateur HTML formate avec js-beautify et minifie avec CSSO et Terser pour les styles et scripts intégrés, le tout côté client. Il est particulièrement pratique pour le HTML d’e-mail et le balisage exporté par un CMS, où il y a rarement une étape de build pour faire la compression à votre place.
Minify vs Gzip vs Brotli : comment ils se cumulent
La question centrale : si votre serveur sert déjà du gzip ou du Brotli, devez-vous quand même minifier ? Oui, parce que les deux techniques éliminent des redondances différentes.
La minification retire la redondance syntaxique au niveau de la source : les espaces, commentaires, noms longs et constructions verbeuses qui existent pour la lisibilité humaine. Gzip et Brotli retirent la redondance statistique au niveau des octets : les chaînes et motifs qui se répètent dans le fichier sont remplacés par des codes plus courts. L’un comprend la syntaxe de votre code ; l’autre ne voit qu’un flux d’octets. Parce qu’ils ciblent des choses différentes, les cumuler fonctionne bien.
Une façon concrète de se le représenter : gzip excelle à remarquer que la chaîne function apparaît deux cents fois dans un bundle et à remplacer chaque occurrence par une courte référence arrière. Il n’a aucune idée que getUserPreferences et getUserSettings sont des noms de variables qu’il pourrait raccourcir, ni qu’un bloc entier if (false) { ... } ne s’exécutera jamais. La minification gère exactement cela : les gains structurels et sémantiques auxquels un compresseur au niveau des octets est aveugle. Exécutez-les ensemble et chacun nettoie ce que l’autre ne peut pas voir.
Voici le calcul, dans l’ordre où il se produit réellement :
- La minification seule réduit typiquement le CSS, le JS et le HTML de 20 à 30 %, en retirant espaces et commentaires et en raccourcissant la syntaxe.
- Gzip sur la sortie minifiée retire 60 à 80 % de plus, en encodant les motifs répétés qui subsistent dans le texte.
- Brotli à la place de gzip produit une sortie 15 à 25 % plus petite encore, grâce à un dictionnaire intégré plus grand et à un meilleur algorithme.
En résumé : minifiez d’abord, puis compressez. Le résultat combiné est souvent 80 à 90 % plus petit que la source originale. Les deux ne sont pas mutuellement exclusifs, et en sauter l’un laisse des octets sur la table.
Pourquoi la minification continue-t-elle de tirer son poids par-dessus Brotli ? Trois raisons :
- Une entrée plus petite se compresse plus petit. Un fichier minifié donne au compresseur moins de matière redondante à mâcher, et une entrée plus petite et plus propre produit généralement une sortie plus petite.
- La minification fait des choses que la compression ne peut pas. L’élimination du code mort et les noms de variables courts sont des suppressions sémantiques. Gzip ne comprend pas votre code, il ne voit que des octets, il ne peut donc jamais supprimer une fonction inutilisée ni renommer une variable.
- Le navigateur analyse moins d’octets. Après décompression, le navigateur reçoit le code minifié. Moins de code signifie une analyse et une exécution plus rapides, pas seulement un téléchargement plus petit.
L’ordre n’est pas un choix : il découle de l’endroit où se situe chaque étape. La minification appartient au temps de build (vous ou votre outil de build la faites une fois). La compression appartient au temps de transfert (le serveur la fait à chaque requête, le navigateur décompresse à l’arrivée). Le pipeline est donc naturellement minifier → déployer → le serveur compresse. Vous ne pouvez pas l’exécuter dans l’autre sens : il n’y a aucun moyen de « compresser, puis minifier », parce que la sortie compressée n’est plus du code source.
Il y a une réserve petite mais importante à « minifier puis compresser » : une fois qu’un contenu est déjà compressé, le compresser à nouveau est inutile ou contre-productif. Les ressources déjà binaires et à haute entropie, comme les JPEG, PNG, WebP et polices en WOFF2, ne gagnent rien du gzip ou du Brotli et ne devraient pas figurer du tout dans vos règles de compression de texte. La minification est une transformation purement textuelle, elle ne touche donc jamais ces fichiers ; c’est avec la compression qu’il faut être sélectif. Configurez votre serveur pour compresser les types MIME texte (HTML, CSS, JS, JSON, SVG) et laissez tranquilles les binaires déjà compressés.
Configurer la couche de transfert, c’est-à-dire activer Brotli et définir Content-Encoding, est une préoccupation ops gérée par votre serveur ou votre CDN. Ce guide reste à la couche source, là où la minification se produit. Si vous optimisez la charge utile plus largement, le même raisonnement « économiser des octets à la couche d’encodage » s’applique aussi aux images ; notre guide des formats d’image couvre le volet WebP/AVIF/JPEG de cette histoire.
Quand vous n’avez pas besoin de minifier manuellement
Voici une vérité que beaucoup de publicités pour minificateurs passent sous silence : si vous avez une étape de build, votre sortie de production est déjà minifiée. Les pipelines de build modernes le font automatiquement.
Vite et esbuild minifient le JavaScript et le CSS d’office. Rollup et webpack le font via TerserPlugin et CssMinimizerPlugin. Lightning CSS gère le CSS à vitesse native. Next.js, Astro et les frameworks similaires minifient, font du tree-shaking et découpent les chunks dans leurs builds de production sans que vous leviez le petit doigt. La commande n’est généralement rien de plus que vite build ou npm run build ; la minification fait partie de ce que « build pour la production » signifie, ce n’est pas une étape distincte que vous greffez. Si cela décrit votre projet, faire passer un fichier dans un minificateur séparé après coup est redondant au mieux et nuisible au pire, car re-renommer du code déjà minifié peut produire une sortie déroutante et n’économisera pas d’octets supplémentaires significatifs.
Les outils de build font aussi quelque chose qu’un minificateur autonome ne peut pas : ils minifient dans le contexte de l’ensemble de votre graphe de dépendances. Le tree-shaking, en particulier, ne fonctionne que lorsque le bundler peut voir chaque import et export et prouver qu’une fonction donnée n’est jamais utilisée. Un minificateur mono-fichier n’a aucun graphe sur lequel raisonner : il peut supprimer le code mort à l’intérieur du fichier que vous lui donnez, mais il ne peut pas dire qu’un module importé entier est inatteignable. C’est une autre raison pour laquelle le pipeline de build est le bon foyer pour la minification de production.
Alors, quand un minificateur autonome est-il le bon outil ? Dans les cas où aucune étape de build ne le fait pour vous :
- Sites statiques et pages mono-fichier écrites à la main, sans bundler dans la boucle.
- Modèles HTML d’e-mail, où de nombreux systèmes facturent à l’octet et où il n’y a aucun pipeline de build.
- Extraits tiers et code de widget que vous intégrez dans la page de quelqu’un d’autre.
- Vérifications rapides de taille : collez un bloc, voyez sa taille après minification et ce que vous avez économisé. C’est à cela que sert l’affichage des octets économisés.
- Lire le code minifié de quelqu’un d’autre, où vous exécutez le formateur à l’envers pour le rendre lisible à nouveau.
La décision est simple. Vous avez un build ? Laissez le build minifier. Pas de build, un coup ponctuel, ou juste vérifier une taille ? Un outil en ligne est le chemin le plus rapide, et parce que ces outils s’exécutent entièrement dans votre navigateur, votre code ne quitte jamais votre appareil. Cela compte pour du code propriétaire ou non publié, que vous ne devriez jamais coller dans un formateur côté serveur qui en reçoit une copie. C’est le même argument de confidentialité qui parcourt notre guide de style SQL, l’autre plongée approfondie sur le formatage de ce groupe.
Source maps : déboguer du code minifié
Le code minifié est un cauchemar de débogage à lui seul. Une fois que Terser a renommé chaque variable locale en a, b et c, une trace de pile de production qui pointe vers bundle.min.js:1:48211 ne vous dit pour ainsi dire rien sur ce qui a réellement cassé.
Les source maps résolvent cela. Une source map est un fichier .map qui enregistre la correspondance entre chaque position dans la sortie minifiée et la position correspondante dans votre source originale. Quand les DevTools du navigateur la chargent, ils retraduisent les erreurs minifiées en vrais noms de fichiers, numéros de ligne et noms de variables. Vous déboguez contre le code que vous avez écrit, même si le navigateur exécute le code que votre build a produit.
En pratique, votre outil de build génère la source map à côté du bundle minifié, et un commentaire //# sourceMappingURL=bundle.min.js.map (ou un en-tête HTTP) indique au navigateur où trouver le .map. Ouvrez les DevTools, rencontrez une erreur, et la trace de pile affiche vos vrais noms de fichiers et numéros de ligne au lieu de la soupe minifiée. La carte est chargée paresseusement, uniquement lorsque les DevTools sont ouverts, elle ne coûte donc rien à vos visiteurs.
Il y a un angle de confidentialité à connaître. Une source map publique expédie de fait votre code source original à quiconque ouvre les DevTools. Pour du code ouvert, c’est très bien ; pour du code propriétaire, non. C’est à cela que servent les source maps cachées : le bundle ne porte aucun commentaire sourceMappingURL, donc le public ne voit jamais la carte, mais vous la téléversez quand même vers un service de surveillance d’erreurs comme Sentry. Le service dé-minifie les traces de pile de production de son côté, vous donnant des erreurs lisibles sans exposer votre source au monde entier.
Remarquez comment cela renforce le point précédent : les source maps sont une capacité de l’outil de build. Un simple minificateur en ligne n’en produit généralement pas, parce qu’une compression ponctuelle n’en a pas besoin. C’est une autre raison de laisser votre build gérer la minification de production : il vous donne la carte gratuitement. Et rappelez-vous qu’une source map ne change jamais le bundle minifié lui-même ; c’est une pure aide au débogage qui se trouve à côté. Ne confondez pas le .map avec une dépendance de production.
Foire aux questions
La minification est-elle la même chose que la compression ?
Non. La minification réécrit votre code source, en retirant espaces et commentaires et en raccourcissant les noms, de sorte qu’il reste du code valide, juste plus petit. La compression (gzip, Brotli) encode les octets résultants pour le transfert, et le navigateur les décode. Elles attaquent des redondances différentes, travaillent à des étapes différentes et se cumulent : minifiez d’abord, puis compressez.
Dois-je minifier si j’utilise gzip ou Brotli ?
Oui. La minification compte encore avec gzip et Brotli. Le code minifié donne au compresseur une entrée moins redondante, donc il se compresse plus petit, et la minification effectue des suppressions sémantiques, comme le code mort et les noms de variables courts, que la compression au niveau des octets ne peut pas faire. Le navigateur analyse aussi moins d’octets. Utilisez les deux, dans cet ordre.
Est-ce que minifier casse mon code ?
Un minificateur conforme préserve le comportement : le CSS s’affiche à l’identique, et Terser garde le JavaScript équivalent. La sortie s’exécute comme la source. Deux mises en garde : le JavaScript qui repose sur l’insertion automatique de point-virgule a besoin d’une syntaxe valide, et le HTML sensible aux espaces comme <pre> ou <textarea> devrait être vérifié après minification.
Quelle est la différence entre minify et uglify ?
Ils signifient en pratique la même chose pour le JavaScript. « Uglify » vient d’UglifyJS, un des premiers minificateurs JS populaires ; Terser en est le fork moderne qui prend en charge la syntaxe actuelle. Aujourd’hui on dit « minify » de manière générique pour CSS, JS et HTML, tandis que « uglify » est un nom plus ancien, spécifique au JS, pour le même processus.
Dois-je minifier en développement ?
Non. Minifiez les builds de production, pas le développement. Le code minifié est illisible et difficile à déboguer, vous voulez donc une source complète et formatée pendant que vous développez. Votre outil de build, qu’il s’agisse de Vite, esbuild ou webpack, minifie automatiquement quand vous buildez pour la production, souvent avec des source maps pour que vous puissiez quand même déboguer le bundle déployé.
De combien la minification réduit-elle la taille du fichier ?
La minification seule réduit typiquement le CSS, le JS et le HTML d’environ 20 à 30 %, surtout en retirant espaces et commentaires et en raccourcissant les noms. Superposée à gzip ou Brotli par-dessus, le résultat combiné est souvent 80 à 90 % plus petit que la source originale. Le chiffre exact dépend de la quantité d’espaces et de redondance que le fichier contenait.