welcome js third parties hosting

Anthony Barré, CTO chez Fasterize, a publié cet article en V.O. anglaise dans le Perf Calendar 2019. Voici la traduction en français.

Depuis quelques années, de plus en plus d'outils et de solutions d'optimisation des performances web proposent un hébergement ou des services de proxy pour des ressources tierces, afin d'optimiser la vitesse de chargement des pages par le navigateur.
Akamai permet par exemple de paramétrer un comportement spécifique pour les URLs générées dans le cadre d’une telle démarche, Cloudflare dispose - aussi dans ce sens - d’un Edge Worker, et Fasterize peut réécrire les URLs d’une page pour référencer des scripts tiers via le domaine principal.

Si vos services ou scripts tiers ne changent pas souvent, et que vous avez besoin d’optimiser la gestion des ressources pour améliorer la vitesse de chargement de vos pages, un service de proxy est une option. Il vous permet d’améliorer leur localisation et ainsi mieux prendre en charge leur mise en cache côté client. 

Vous vous assurez également qu’en cas de panne ou de dégradation des performances de l’éditeur de vos services tiers, vos utilisateurs ne seront pas affectés.

Avantage de l’auto-hébergement des ressources tierces : l'optimisation des performances

Si vous hébergez des services tiers, l'impact sur les performances et sur la vitesse de chargement de vos pages est simple : le navigateur enregistre une résolution DNS, une connexion TCP et une négociation TLS sur un domaine tiers ; et le navigateur profite du multiplexage et de la hiérarchisation HTTP/2 établis sur le domaine principal.
Vous pouvez observer la différence qui en découle entre les deux waterfalls ci-dessous :

Waterfall JS Third parties 1

 

Waterfall JS Third parties 2

Sans auto-hébergement, étant donné que les ressources tierces sont servies à partir d'un domaine différent de la page, elles ne peuvent pas être hiérarchisées et finissent par se faire concurrence pour la bande passante, ce qui peut ralentir considérablement la récupération des autres ressources critiques, et donc dégrader la vitesse de chargement et l'expérience pour vos utilisateurs. Patrick Meenan explique très bien ce phénomène dans son talk sur la priorisation HTTP/2.

Nous pourrions supposer que tenter de préconnecter chaque domaine tiers critique pourrait régler le problème, mais en pratique, la préconnexion d'un trop grand nombre de domaines peut surcharger la bande passante, ce serait donc contre-productif.

Ainsi, en auto-hébergeant des ressources tierces, vous contrôlerez la façon dont elles sont servies :

  • vous vous assurez que le meilleur algorithme de compression est utilisé pour chaque navigateur (Brotli / Gzip) ;
  • vous pouvez étendre le temps de mises en cache qui sont traditionnellement courts, même pour le fournisseur le plus connu (eg. une balise GA à 30mn) ;
  • vous pouvez même étendre le Time To Live (ou TTL) à un an en incluant ces assets dans votre stratégie de gestion du cache (hachage d'URL, versioning, etc.). Nous verrons ce point plus loin dans l'article.

Aucune interruption de service

Un autre aspect intéressant de l'auto-hébergement de ressources tierces est l'atténuation des risques associés aux ralentissements et aux pannes. Supposons que votre solution de test A/B soit très lente et implémentée en tant que script bloquant dans la section head du code HTML de votre page, le résultat est que soit la page restera vierge, soit la page aura besoin d’un certain temps pour s’afficher.
Par ailleurs, si vous utilisez une bibliothèque à partir d'un CDN tiers, vous risquez de casser la logique JavaScript de votre site web si le fournisseur tiers est en panne ou bloqué dans un pays.

Vous pouvez consulter la section SPOF sur Webpagetest pour vérifier le comportement de votre site web lorsqu'un service externe est interrompu :

SPOF Webpagetest Webperf

Quid de la pénalité de mise en cache du navigateur ? (spoiler : c'est un mythe)

Vous pouvez penser que l'utilisation du CDN public entraînera automatiquement de meilleures performances pour un chargement rapide du contenu, car il a un meilleur réseau et il est distribué, mais la réalité est plus complexe.

Prenons l’exemple de différents sites web : site Web1.com, site Web2.com, site Web3.com. Nous utilisons jQuery sur chacun d'eux et l'incluons à partir d’un CDN comme googleapis.com. Le comportement attendu d'un navigateur serait de le mettre en cache une bonne fois pour toutes et de l'utiliser pour tous les autres sites Web. Cela réduirait les coûts d'hébergement des sites et améliorerait les performances.
Mais en pratique, ce n'est pas ce qui se passe. On l’observe notamment avec Safari qui implémente une fonctionnalité appelée Intelligent Tracking Protection - le cache est à double clé basé sur l'origine du document et sur l'origine tierce. C’est très est bien expliqué dans cet article Safari, mise en cache et ressources tierces d'Andy Davies. Chrome va aussi partitionner son cache.

Aussi, des recherches de Yahoo, Facebook et plus récemment de Paul Calvano, ont démontré que les ressources ne vivent pas aussi longtemps que nous pourrions nous y attendre dans le cache du navigateur :

“Il y a un écart important entre l'âge des ressources propriétaires et celui des scripts tiers pour des polices CSS et web. 95 % des polices propriétaires ont plus d'une semaine, contre 50 % des polices tierces qui ont moins d'une semaine ! Cela constitue un argument solide en faveur de l'option des polices web auto-hébergées !”

Pour ces raisons, vous ne remarquerez aucune dégradation des performances due à la mise en cache du navigateur !

Maintenant que nous avons vu les avantages de l’auto-hébergement des ressources tierces, voyons ce qui fait la différence entre une bonne et une mauvaise implémentation.

Les risques : le diable se cache dans les détails

Le rapatriement de ressources tierces sur le domaine principal ne peut pas être effectué automatiquement sans prendre en considération la mise en cache.

Alors, attention au cycle de vie des ressources !

Bonne nouvelle : les scripts tiers versionnés comme jquery-3.4.1.js ne causeront aucun problème de mise en cache car aucune modification ne se produira sur ce fichier à l'avenir.

Mais s'il n'y a pas de versionning en place, les scripts peuvent devenir obsolètes. Cela peut devenir un gros problème car vous passerez à côté des correctifs de sécurité importants si vous ne procédez pas à des mises à jour manuelles, et vous pouvez même générer des bugs en cas de désynchronisation entre un tag et son backend.

Néanmoins, si la mise en cache d'une ressource sur le CDN régulièrement mise à jour (gestionnaires de tags, solutions de test A/BB) est plus difficile, elle reste possible. Des services comme Commander Act, une solution de gestion de tags, demandent un webhook lorsqu'une nouvelle version est publiée. Cela permet de flusher le CDN, ou mieux, de déclencher une mise à jour dans le hash / version de l'URL.

L’Adaptive Serving

Lorsque nous parlons de mise en cache, nous devons tenir compte du fait que les options ou paramètres de cache sur le CDN peuvent ne pas convenir à des ressources tierces. Les services tiers peuvent implémenter le UserAgent-sniffing (également appelé Adaptive Serving) pour servir des versions optimisées pour un navigateur donné.
Ils s'appuient sur une expression régulière ou une base de données sur l'en-tête HTTP du User-Agent pour connaître les capacités des navigateurs et proposer la version qui convient.

Deux cas me viennent à l'esprit pour illustrer ce principe : googlefonts.com et polyfill.io.
Google Fonts sert au moins 5 versions de fichier CSS différentes pour une ressource en fonction de la capacité UserAgent (référencement de WOFF2, plage unicode…).

Police Google demandée par la navigateur Chrome :

Font Chrome web performance JS Third Parties

Police Google demandée par le navigateur IE10 :

Font IE10 web performance JS Third Parties

Polyfill.io, quant à lui, renvoie uniquement les polyfills requis par le navigateur pour des raisons de performance.

Ainsi, la taille de la requête de https://polyfill.io/v3/polyfill.js?features=default est de 34 Ko lorsqu'elle est chargée par le navigateur IE10, et vide lorsqu'elle est chargée par un navigateur Chrome.

L’envers du décor : quelques mots sur les problèmes de confidentialité

Sachez toutefois que la prise en charge des scripts tiers via le domaine ou le sous-domaine principal n'est pas neutre pour la confidentialité des utilisateurs et pour votre entreprise.

Si votre CDN est mal configuré, vous risquez d’envoyer les cookies de votre propre domaine à un service tiers. Votre cookie de session, qui n'est normalement pas exploitable en Javascript (avec l'attribut httponly), sera alors envoyé à un hôte tiers s'il n'y a pas de filtrage au niveau CDN.

C'est exactement ce qui a pu arriver avec des trackers comme Eulerian, Criteo… Les trackers tiers étaient en mesure de définir un identifiant unique dans les cookies qu'ils pouvaient ensuite  lire librement sur les différents sites Web visités tant que ce tracker tiers était inclus par le site.

Désormais, la plupart des navigateurs prévoient des protections contre cette pratique. Ainsi, ils demandent de déguiser ces tiers en trackers propriétaires derrière un sous-domaine aléatoire, avec un CNAME vers un domaine générique et sans marque. Cette méthode est appelée CNAME Cloaking.

Bien que cela soit considéré comme une mauvaise pratique pour un site Web de définir des cookies accessibles à tous les sous-domaines (c'est-à-dire * .website.com), de nombreux sites le font. Dans ce cas, ces cookies sont automatiquement envoyés au tracker tiers masqué - game over.

Le même phénomène se produit avec les en-têtes HTTP Client-Hints qui sont uniquement envoyés au domaine principal, car ils peuvent être repris pour créer un “fingerprint” permettant de tracker l’utilisateur. Assurez-vous que votre CDN filtrera également correctement ces en-têtes.

Conclusion

Si vous voulez auto-héberger des ressources tierces, voici quelques astuces pour optimiser la vitesse de chargement de vos pages et offrir la meilleure expérience à vos utilisateurs :

  • auto-hébergez vos bibliothèques JavaScript, polices et CSS critiques. Cela réduira le risque de SPOF ou de dégradation des performances sur le chemin critique.
  • avant de mettre en cache une ressource tierce sur un CDN, assurez-vous qu'elle est versionnée ou que vous pouvez gérer son cycle de vie en vidant manuellement ou même automatiquement le CDN lorsqu'une nouvelle version est publiée.
  • vérifiez votre configuration CDN / proxy / cache pour éviter d'envoyer des cookies de votre domaine et des Clients-Hints à des services tiers.

Vous souhaitez suivre les actualités de la web performance et l'évolution des bonnes pratiques,
abonnez-vous à notre newsletter mensuelle :

Je m'abonne !


Hello SMX Paris !