Makina Blog

Le blog Makina-corpus

Optimiser le chargement des publicités en asynchrone


Les publicités phagocytent la bande passante, voici comment les inviter en dernier dans le chargement de votre page.

Ces petits encarts qui permettent à certains sites de subvenir à leurs besoins ralentissent souvent le chargement d'une page. La majorité des régies publicitaires fournissent un tag à inclure dans le head de la page HTML, puis appellent l'encart à travers une fonction chargée dans ce tag.

<html><head>
  <script src="http://maregiepub.lol/monscript.principal.js" />
</head><body>
  <header><div id="Top"><script>ChargerPub('Top');</script></header>
  <main>Mon beau contenu, roi de la SEO</main>
  <aside><div id="Right"><script>ChargerPub('Right');</script></aside>
</body></html>

Avec cette technique, on se retrouve à charger dès le début de la page une ressource externe, dont on ne peut prévoir le temps de chargement, puis à charger les encarts quand le navigateur "lit" (sous-entendre "parse") les scripts inline. Quand bien même les encarts chargeraient leurs images ou objets flash en asynchrone, cette technique resterait très pauvre en performances :

  • évènement onContentLoad: 3,531s, en bleu, la page s'affiche pour l'utilisateur
  • évènement onLoad: 5,639s, en rouge, la page et ses ressources sont totalement chargées
  • en vert, les requêtes concernant la publicité

Avant optimisation

En essayant de placer le tag principal en bas de page, parce qu'on adopte les bonnes pratiques, la fonction ChargerPub() renverra des erreurs JS undefined, logique. Du coup, on essaie de pallier le problème en tentant d'appeler cette fonction jusqu'à ce qu'elle soit disponible :

<html><head></head><body>
  <header>
    <div id="Top"><script>ChargerPubAsync('Top');</script></div>
  </header>
  <main>Mon beau contenu, roi de la SEO</main>
  <aside>
    <div id="Right"><script>ChargerPubAsync('Right');</script></div>
  </aside>
  <script src="http://maregiepub.lol/monscript.principal.js" />
  <script>
    function ChargerPubAsync(param) {
        var tryChargerPub = function() {
          if (typeof ChargerPub == 'undefined') {
            setTimeout(tryChargerPub(), 100);
          }
          else {
            ChargerPub(param);
          }
        }
        tryChargerPub();
    }
  </script>
</body></html>

Sauf que voilà, ça ne fonctionne pas, n'essayez pas non plus de placer l'attribut async ou defer, car si l'on regarde de plus près ce que fait la régie pub, elle utilise la fonction document.write() à profusion, avec parfois des chargements d'autres scripts, d'où le fait qu'elle demande de placer la fonction à un endroit précis dans le HTML, celui où l'encart doit apparaître.

Comme JavaScript est très flexible, on pourrait imaginer surcharger document.write(), créer un buffer pour le HTML retourné, charger également les scripts, le tout en mode récursif. Arrêtez-vous là, d'autres l'ont fait avant vous.

Il s'agit de PostScribe, ce script fait exactement ce qui est prévu : il crée un buffer pour récupérer tout ce que peuvent écrire les requêtes Ajax via document.write() et remet tout le HTML dans un élément défini par un ID. On peut même lui donner une callback pour exécuter des fonctions une fois que la régie pub a fini son travail.

Voila ce à quoi on arrive au niveau code :

<html><head></head><body>
  <header><div id="Top"></div></header>
  <main>Mon beau contenu, roi de la SEO</main>
  <aside><div id="Right"></div></aside>
  <div id="#nothing" class="hidden"></div>
  <script src="http://cdn.lol/jquery_et_postcribe.js"/>
  <script>
    jQuery(function () {
      postscribe('#nothing', '<scr' + 'ipt src="http://maregiepub.lol/monscript.principal.js"><\/scr' + 'ipt>', {
        done: function () {
          postscribe('#Top', '<sc' + 'ript language="JavaScript">ChargerPubAsync(\'Top\');</scr' + 'ipt>');
          postscribe('#Right', '<sc' + 'ript language="JavaScript">ChargerPubAsync(\'Right\');</scr' + 'ipt>');
        }
      });
    });
    //-->
  </script>
</body></html>

Notez que j'ai utilisé un <div id="nothing"></div>, je m'en sers pour que postscribe crache ce qu'il veut dedans (l'Ajax de la régie renvoie parfois du garbage HTML).

Les performances sont bien meilleures puisque l'utilisateur peut naviguer tranquillement pendant que les pubs se chargent, le FOUC (Flash Of Unstyled Content) est réduit, car l'événement onContentLoad est plus rapide :

  • évènement onContentLoad: 1,140s (en bleu), on a divisé par deux le temps d'affichage visible de chargement de la page pour l'utilisateur
  • évènement onLoad: 5,581s (en rouge),
  • en vert, les requêtes concernant la publicité

Après optimisation

Pour le reste du chargement de la page, notez que les requêtes relatives au site représentent moins de 20 requêtes, les 3/4 de la totalité des requêtes concernent la publicité (snif).

Pour en savoir plus sur l'optimisation front-end, n'hésitez pas à vous inscrire au prochain petit-déjeuner le mercredi 8 avril sur les outils du développeur front-end (Gulp, Less/Sass, Bootstrap, etc.), ou venez me rencontrer aux Drupal Developer Days à Montpellier du 10 au 19 avril.

Actualités en lien

Image
Capture d'une partie de carte montrant un réseau de voies sur un fond de carte sombre. Au centre, une popup affiche les information de l'un des tronçons du réseau.
28/02/2024

Géné­rer un fichier PMTiles avec Tippe­ca­noe

Exemple de géné­ra­tion et d’af­fi­chage d’un jeu de tuiles vecto­rielles en PMTiles à partir de données publiques.

Voir l'article
Image
Read The Docs
01/02/2024

Publier une documentation VitePress sur Read The Docs

À l'origine, le site de documentation Read The Docs n'acceptait que les documentations Sphinx ou MKDocs. Depuis peu, le site laisse les mains libres pour builder sa documentation avec l'outil de son choix. Voici un exemple avec VitePress.

Voir l'article
Image
Widget
04/04/2023

Créer une application en tant que composant web avec Stencil

Mise en place dans le cadre de Geotrek, cette solution permet de se passer d'une iFrame pour afficher une application dans n'importe quel site.

Voir l'article

Inscription à la newsletter

Nous vous avons convaincus