optimisations des fonts webperf

Dans notre article Webperf : Comment optimiser le chargement des fonts ?, nous avions démontré l’impact du chargement des fonts sur les performances d’un site.
Nous avions notamment constaté que le Speed Index et le Start Render baissaient en moyenne de 5 à 10% lorsque les fonts n’étaient pas chargées.

En matière d’optimisation de fonts, l’outil généralement conseillé est Font-Squirrel. C’est un super outil, mais qui a l’inconvénient d’être manuel. Nous avons donc gardé les meilleures fonctionnalités de celui-ci pour développer notre moteur d’optimisation de fonts automatique.
Au programme :

  1. génération des polices au format WOFF2
  2. mise à jour automatique de la déclaration CSS @font-face
  3. ajout de la propriété font-display
  4. minification des fonts via la technique du subsetting
  5. autohint des polices pour un meilleur rendu visuel sous Windows
  6. optimisation du chargement des polices Google Font

Au niveau du dashboard, vous pouvez régler l’ensemble des paramètres des optimisations des fonts dans la partie configuration :

font optimization webperf

1. La génération automatique des fonts en WOFF2

WOFF2 est le format de police de caractères le plus avancé. Il a l’avantage de réduire le poids des fichiers de 30% en moyenne et plus de 50% dans certains cas par rapport au format WOFF.

Le changement principal par rapport au format WOFF est le passage à l’algorithme de compression brotli au lieu de gzip (ou zopli). Par ailleurs, il mémorise le corps d'un caractère sans accent, et le réutilise pour le représenter avec accent (il n’est plus nécessaire d’avoir un caractère pour chaque accent).

WOFF2 est actuellement supporté par tous les navigateurs récents (83% des navigateurs utilisés en France).

WOFF 2.0 - Web Open Font Format

Concrètement, le moteur Fasterize est maintenant capable d’interpréter un nouveau type d’URL de conversion de format de la forme :
http://www.domain.com/fstrz/r/c/www.domain.com/fichier.woff.woff2

Le chemin du fichier source se trouve entre /fstrz/r/c et l’extension .woff2. Dans l’exemple ci-dessus, le fichier source est http://www.domain.com/fichier.woff. Ce format repose sur notre mécanisme de réécriture d’URL actuellement utilisé pour la fonctionnalité d’unsharding.

Ce schéma d’URLs permet de générer le format WOFF2 à partir des formats suivants : TTF (truetype), OTF (opentype) et WOFF (Web Open Font Format). Le format EOT (embedded-opentype) est un format trop ancien qui n’est utile que pour les vieux navigateur Internet Explorer. Ce format n’est pas supporté par Fasterize.

Même si l’utilité est moindre, Fasterize saura générer le format WOFF ou TTF pour les navigateurs ne supportant pas WOFF2. Par exemple, l’URL suivante permet de générer la font au format WOFF à partir du format TTF:
http://www.domain.com/fstrz/r/c/www.domain.com/fichier.ttf.woff

Chez nos clients test, certains fichiers Font sont passés de 173 Ko (en WOFF) à 99 Ko (en WOFF2), soit un gain de près de 43%.

2. Mise à jour automatique de la propriété src des déclarations @font-face

Fasterize se charge aussi de mettre à jour la propriété src des déclarations @font-face de façon automatique.

Pour illustrer la mise à jour de la propriété, considérons la déclaration @font-face suivante (absolument pas optimisée) :

@font-face {
	font-family: 'MyFontFamily';
	src: url('myfont-webfont.ttf') format(‘true-type’), url('myfont-webfont.svg');
	}

La propriété src des déclarations @font-face est une liste priorisée des différentes formats possible du fichier. Le navigateur va choisir la source du fichier en examinant les éléments de la liste dans l’ordre. Pour détecter le format du fichier, le navigateur se basera sur le format renseigné dans la fonction “format” de chaque source. Il est donc indispensable de placer le format le plus compressé en premier.

Notre moteur va effectuer les actions suivantes :
rajouter le format WOFF et WOFF2 s’ils ne sont pas présents dans la propriété.
placer les sources dans le bon ordre en tenant compte du hack pour supporter Internet Explorer 9 (#iefix)
ajouter les déclarations de format manquantes dans la fonction format (Dans l’exemple précédent, le format truetype).

Voici la déclaration modifiée par le moteur :

@font-face {
  font-family: 'MyFontFamily';
  src: 
       url('http://www.domain.com/fstrz/r/c/myfont-webfont.ttf.woff2') format('woff2'),
       url('http://www.domain.com/fstrz/r/c/myfont-webfont.ttf.woff') format('woff'),
       url('myfont-webfont.ttf')  format('truetype'),
       url('myfont-webfont.svg#svgFontName') format('svg');
  }

De la même manière que le navigateur, notre moteur va déterminer le format des différentes sources grâce aux indications suivantes par ordre de priorité :

  1. la déclaration du format dans la fonction format. Par exemple format (woff).
  2. l’extension dans l’URL.
  3. la déclaration du mime-type si la police est inlinée en base64.

Une pratique répandue pour diminuer les temps de téléchargement est d’intégrer la font en base 64 dans la déclaration @font-face. Prenons l’exemple de la déclaration suivante :

@font-face {
  font-family: 'MyFontFamily';
  src: 
       url('data:application/x-font-woff;base64,d09GRgABAAAAAEwMAA0AAAAAjawA.....') format('woff'),
       url('myfont-webfont.ttf')  format('truetype');
  }

Cette pratique vise à éliminer une requête HTTP sur le chemin critique et aussi éviter un flash au niveau du texte. Cependant, elle est aujourd’hui dépréciée à l’heure d’HTTP/2, de la balise preload et de la déclaration font-display. Cela ralentit l’analyse du CSS et sature la bande passante.

Le moteur ne va pas bêtement insérer une source WOFF2 avant la source WOFF inlinée comme ceci :

@font-face {
  font-family: 'MyFontFamily';
  src: 
       url('http://www.domain.com/fstrz/r/c/myfont-webfont.ttf.woff2') format('woff2'),
       url('data:application/x-font-woff;base64,d09GRgABAAAAAEwMAA0AAAAAjawA.....') format('woff'),
       url('myfont-webfont.ttf')  format('truetype');
  }

Cela aurait pour conséquence de télécharger deux fois le même fichier (une fois en WOFF2 et une fois dans le corps du fichier CSS.

Au contraire, le moteur va avoir deux comportements :

  • s’il a la possibilité de retrouver l’URL du fichier source à partir d’une déclaration d’un autre format (par exemple TTF), il va alors réécrire deux URLS pour les formats WOFF et WOFF2. L’inlining du format WOFF n’est alors pas conservé.
    @font-face {
      font-family: 'MyFontFamily';
      src: 
           url('http://www.domain.com/fstrz/r/c/myfont-webfont.ttf.woff2') format('woff2'),
           url('http://www.domain.com/fstrz/r/c/myfont-webfont.ttf.woff') format('woff'),
           url('myfont-webfont.ttf')  format('truetype');
      }
  • s’il n’a pas la possibilité de retrouver l’URL à partir d’un autre format, le format WOFF2 ne sera pas ajouté dans les sources. La déclaration sera inchangée.

3. L’ajout de la propriété font-display de la déclaration @font-face

La propriété font-display est une propriété supportée par les navigateurs Chrome et qui va faire son apparition sur Firefox 58. Elle laisse le développeur décider comment les fonts sont appliquées (ou non), en fonction de leur temps de téléchargement. Vous pouvez lire le détails de cette propriété ici CSS Font Rendering Controls Module Level 1.

@font-face {
  font-family: "Open Sans Regular";
  font-weight: 400;
  font-style: normal;
  src: url("fonts/OpenSans-Regular-BasicLatin.woff2") format("woff2");
  font-display: swap;
}
CSS Font Rendering Controls

Sans cette propriété, votre navigateur adopte différents comportements pendant que la font se télécharge :

  • Le FOUT : le Flash Of Unstyled Text, le navigateur affiche le texte dans une font non stylisée avant d'afficher la bonne font. C’est le cas des navigateurs Internet Explorer, Edge.
  • Le FOIT : le Flash Of Invisible Text, le navigateur n'affiche pas le texte tant que la font n'est pas chargée. Le texte reste donc invisible. C’est le cas des navigateurs Chrome, Firefox, Safari, Opera. Pour éviter ce SPOF, Chrome, Firefox et Opera attendront au maximum 3 secondes avant d’afficher du texte.
FOUT vs FOIT

Depuis le dashboard, vous pouvez désormais choisir l’un des comportements possibles par la propriété font-display :

  • auto : la stratégie d'affichage de la font est définie par le user agent.
  • block : le texte n’est pas affiché tant que la font n'est pas chargée (cf FOIT ci-dessus)
  • swap : le texte sera immédiatement affiché non stylé et est remplacé par la bonne font une fois téléchargée (cf FOUT ci-dessus). C’est souvent le comportement ciblé par des solutions en Javascript basé sur FontObserver.
  • fallback : c’est un compromis entre auto et swap. Il y aura une faible période de temps (100ms d’après Google) pendant laquelle le texte ne sera pas visible puis le texte non stylé sera affichée. Une fois la font chargée, le texte sera stylé.
  • optional : opère comme fallback, le texte est initialement invisible pendant une faible période puis devient visible mais non stylé. Cependant, le navigateur peut décider de ne pas utiliser la font sur des connexions lentes ou encore n’utiliser la font que si elle est déjà en cache.
font block swap fallback optional

Le mode conseillé que nous appliquons par défaut est le swap. C’est en effet, celui qui assure un affichage du texte rapide.

4. Le subsetting, ou la minification des fonts

Le subsetting permet de réduire le nombre de caractères contenus dans le fichier selon une langue ou une plage unicode donnée. Il s’agit en quelque sorte d’une minification adaptée aux polices de caractère : nous supprimons tous les caractères inutiles.

Dans cet exemple, nous ne gardons que les caractères du range unicode : basic-latin.

range unicode

Le point intéressant de cette technique est le fait qu’il y a une relation proche de un pour un entre le poids du fichier et le nombre de caractères. C’est donc une technique très efficace pour diminuer le poids du fichier.

Pour vous simplifier la vie, nous supportons aussi le subsetting par langue. Si votre site est en français, il vous suffit de choisir la langue française dans le menu. Si au contraire, votre site est traduit en plusieurs langues latines d’europe occidentale, nous vous conseillons de choisir le range “latin”.

La difficulté d’un subsetting automatisée réside dans la gestion des polices n’ayant pas de caractères dans la plage unicode ciblées. Le cas le plus répandu est le cas des fichiers d’icônes (comme Font-Awesome). Notre moteur détecte ce type de fichier pour ne pas supprimer les caractères.

Dans le cas de site en test, cette optimisation nous a permis de réduire encore le poids de fichiers des fonts de 79%, en passant de 99 Ko (avec WOFF2) à 21 kb.

5. L’autohint pour un meilleur rendu sous Windows

Le hinting est une technique fondamentale de la génération des fonts. Ce sont des indications de rendu incluses dans le fichier permettant d’ajuster la font pour une meilleure lecture sur certain OS. Cela permet d’assurer des arrondis sur certains caractères.
Windows nécessite un hinting pour avoir un rendu correcte des fonts alors que les moteur de rendu de Mac OS et Linux ne les utilisent pas. Celui-ci est adaptable en fonction du moteur de rendu des fonts de Windows (ClearType, DirectWrite).

autohint

Comme dans la plupart des générateurs de fonts tels que Font-Squirrel, notre moteur va appliquer de façon systématique ttfautohint sur les fonts générées. Cela permet de nous assurer que les hints sont bien présents dans le fichier.

6. Optimisation du chargement des polices Google Font

Les polices téléchargées via Google Font sont optimisées pour le navigateur et l’OS en terme de format et de déclaration CSS. Le format WOFF2 et la propriété unicode-range sont alors utilisées.
Cependant, pour accélérer le rendu de ces fonts, nous vous conseillons d’ajouter une balise link rel=preconnect dans votre tag manager Fasterize.

ajouter une balise link rel=preconnect dans votre tag manager Fasterize

Cela permet d’initier une connexion vers fonts.gstatic.com utilisée par Google Fonts avant même d’avoir téléchargé le fichier CSS. Cela permet de gagner de précieuses millisecondes sur le chemin critique du rendu (métrique du start render).

fonts.gstatic.com

Conclusions

Cet ensemble d’optimisations a été développé avec le souci d’assurer une cohérence d’ensemble sur le chargement des fonts. Chaque optimisation est complémentaire et vous permet une fois de plus de gagner de la flexibilité et du temps.
Pour y accéder, il suffit de vous connecter à votre Dashboard Fasterize, d’aller dans vos paramètres (settings) et d’afficher les options de l’optimisation du chargement des polices de caractères.

Et si vous n’avez pas encore fasterizé votre site web, vous pouvez toujours …

Demandez votre diagnostic de vitesse gratuit

VOUS AIMEREZ PEUT-ÊTRE AUSSI...

Préchauffer le cache : pourquoi, comment ? Dans cet article, nous vous invitons à décortiquer la problématique du préchauffage du cache. Nous l'aborderons dans un premier temps sous l...
La Check-list webperf avant les soldes Les soldes approchent (J-3) et la performance de votre site web sera un axe important de votre réussite. Améliorer les temps de chargement p...
Yellow Lab Tools + Fasterize = 💙 Nous vous en avions déjà parlé dans notre article sur les outils incontournables pour analyser la performance de votre site web. Yellow Lab ...
Meetup Paris Webperf : Ce qu’il ne fallait pas man... Le monde de la performance web était réuni pour un meetup chez Mozilla. Au programme de cette belle soirée : Nicolas Hoizey, Directeur Innov...