Optimiser la priorité JavaScript pour des chargements de page plus rapides

Apprenez à prioriser efficacement les scripts pour améliorer les Core Web Vitals.

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2024-12-12

Gérer les priorités JavaScript pour une meilleure performance Web

Une chose a toujours été claire : tous les JavaScript ne sont pas égaux. Certains scripts gèrent des interactions critiques comme l'interaction avec le menu ou l'ajout au panier, tandis que d'autres sont bien moins importants. Prenons votre script de popup 'exit intent' qui invite les visiteurs sur le point de quitter votre site à remplir un questionnaire. Je suis sûr que nous pourrions tous vivre sans les derniers, mais il serait vraiment difficile de naviguer sur un site Web sans les premiers.

Pourtant, sur 'votre site Web moyen', cette distinction n'est presque jamais faite au niveau technique. Tous les JavaScripts sont 'juste ajoutés' à la page et le navigateur est laissé à lui-même pour se débrouiller. C'est un problème car votre navigateur n'a aucune idée de ce qui est important et de ce qui ne l'est pas. Nous, en tant que développeurs, le savons. Alors corrigeons cela !

Comment la priorité JavaScript peut impacter les Core Web Vitals

Le simple ajout de scripts à la page sans la considération appropriée peut impacter les 3 Core Web Vitals : le Largest Contentful Paint, l 'Interaction to Next Paint et le Cumulative Layout Shift. 

javascript lcp impact example

Exemple : la ressource réseau LCP est retardée par des JavaScripts bloquant le rendu

Le Largest Contentful Paint est sujet à la concurrence de la bande passante et du CPU. Lorsque trop de scripts se battent pour les ressources réseau précoces, cela retarde la ressource réseau du Largest Contentful Paint et le travail CPU précoce retarde le LCP en bloquant le fil principal.

L'Interaction to Next Paint peut être affecté par des scripts s'exécutant juste avant une interaction. Lorsque les scripts s'exécutent, ils bloquent le fil principal et retardent toute interaction pendant ce temps d'exécution.

Les scripts peuvent également causer un Cumulative Layout Shift si les scripts 'changent l'apparence de la page'. Les scripts publicitaires qui injectent des bannières dans la page et les sliders sont connus pour faire cela.

5 types de priorités JavaScript

J'aime distinguer 5 types de priorités JavaScript. Discutons-en rapidement avant de creuser.

  • Critique pour le rendu : ces scripts sont parmi les pires à avoir. Ils changent la mise en page et sans charger ces scripts, la mise en page sera complètement différente. Exemple : certains scripts de slider ou un test A/B.
  • Scripts critiques : Ces scripts gèrent des fonctionnalités critiques de la page et sans eux, des tâches critiques comme l'ajout d'un produit au panier, la recherche sur le site ou la navigation ne sont pas possibles.
  • Scripts importants. Ces scripts gèrent une logique (métier) importante et votre site en dépend. Par exemple : Analytics
  • Scripts 'Nice to have'. Ces scripts sont agréables à avoir mais en cas de besoin absolu, nous n'en avons pas vraiment besoin pour que la page fonctionne. Par exemple, un widget de chat ou un exit intent.
  • Scripts futurs. Ces scripts peuvent être critiques ou agréables à avoir, mais nous n'en avons pas besoin tout de suite car d''autres étapes' doivent être franchies avant que nous puissions réellement utiliser ces scripts. Par exemple, un script de paiement en plusieurs étapes.
Maintenant que nous avons une idée des priorités des scripts, analysons cela !

1. Scripts critiques pour le rendu

Ce sont les scripts les plus perturbateurs, car ils impactent directement la façon dont la page est affichée. Sans eux, la mise en page peut se casser ou apparaître radicalement différente de sa conception prévue. Les exemples incluent des scripts pour des sliders ou des frameworks de test A/B qui modifient la mise en page tôt dans le processus de chargement. 

Le problème avec ces types de scripts est qu'ils ne peuvent pas être différés ou retardés. Tout retard fera bouger la mise en page du site Web, causant une mauvaise UX et l'échec des Core Web Vitals.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Page Title</title>
    <link href="styles.css" rel="stylesheet" />
    <script src="render-critical.js"></script>
  </head>
  <body></body>
</html>

Meilleures pratiques :

  • Évitez les scripts critiques pour le rendu comme celui-ci autant que possible. Réécrivez votre code pour éviter de dépendre de ces types de scripts.
  • S'il n'y a pas moyen de l'éviter, intégrez-les en inline ou ne chargez que les parties absolument nécessaires de ces scripts. 
  • Ne mettez pas ces scripts en defer ou async et placez-les en haut du head pour déclencher un téléchargement 'aussi tôt que possible'.

2. Scripts critiques

Ces scripts permettent des interactions fondamentales. Sans eux, des tâches critiques comme la navigation sur le site, l'ajout d'articles au panier, la notice de cookies ou la réalisation d'une recherche deviennent impossibles. Ils sont indispensables pour la fonctionnalité principale du site.

Ces scripts doivent être placés dans le head de la page avec l'attribut async ou defer.

<script defer src="critical.js"></script>
<script async src="critical.js"></script>

Meilleures pratiques :

  • Gardez les scripts comme ceux-ci au minimum et ne combinez pas cette fonctionnalité avec d'autres fonctionnalités moins critiques.
  • Chargez ces scripts tôt en utilisant async ou defer, selon leurs dépendances.
  • Utilisez des outils de Real User Monitoring (RUM), tels que CoreDash, pour identifier les goulots d'étranglement dans l'exécution et assurez-vous que leur performance correspond aux besoins des utilisateurs.

3. Scripts importants

Bien qu'ils ne soient pas directement liés à l'utilisabilité du site, les scripts importants soutiennent des fonctions commerciales clés. Les scripts d'Analytics, par exemple, fournissent des données essentielles mais n'ont pas besoin de se charger avant des éléments visuels plus importants. Évidemment, la distinction entre scripts critiques et importants peut faire l'objet de débats, alors assurez-vous de parler à toutes les parties prenantes avant de définir cette priorité !

Il existe 3 façons de réduire la priorité des scripts pour ces types de scripts.

<html>
<head>
<!-- method 1: low fetchpriority -->
<script fetchpriority="low" defer src="important.js"></script>

<!-- method 2: inject after DOMContentLoaded -->
<script>
  document.addEventListener('DOMContentLoaded', function() {
    var script = document.createElement('script');
    script.src = 'important.js';
    document.body.appendChild(script);
  });
</script>
</head>
<body>

<!-- method 3: place at the bottom of the page -->
<script defer src="important.js"></script>
</body>
</html>

1. fetchpriority faible. 

Définir la fetchpriority réduira la priorité relative du script. D'autres scripts différés ou asynchrones seront probablement mis en file d'attente avec une priorité élevée tandis que les scripts avec fetchpriority="low" seront mis en file d'attente avec une priorité faible. Selon votre page (ou votre chemin de rendu), cela pourrait être suffisant pour prioriser d'autres ressources comme votre image Largest Contentful Paint et les polices importantes. 

2 : Injecter après DOMContentLoaded

En injectant le script après l'événement DOMContentLoaded, vous vous assurez que le script commence à se télécharger directement après que le HTML a été entièrement analysé. Cela permet aux ressources découvrables, telles que les images et les polices, de prendre la priorité. Cette méthode offre un équilibre : le script commence à se charger assez tôt pour éviter des retards de fonctionnalité mais ne concurrence pas les ressources précoces qui sont cruciales pour le rendu initial de la page.

3 : placer en bas de la page

Cette technique classique diffère le chargement du script jusqu'à ce que le navigateur ait traité l'ensemble du document et obtient à peu près le même résultat que la technique. La seule différence est que la technique 2 ignore le preload scanner de votre navigateur alors que cette technique ne le fait pas.  Le preload scanner est un scanner léger et rapide que votre navigateur utilise pour identifier et mettre en file d'attente rapidement les ressources critiques. Ignorer le preload scanner pourrait être une bonne idée s'il y a une possibilité d'images chargées en lazy load dans le viewport, tandis que l'utilisation du preload scanner accélérera le chargement pour ce script.

4. Scripts 'Nice-to-Have'

Ces scripts améliorent l'expérience utilisateur mais ne sont pas requis pour que le site fonctionne. Les exemples incluent des widgets de chat, des popups de feedback client ou des animations optionnelles. Bien que bénéfiques, ils ne doivent pas interférer avec l'expérience utilisateur principale.

Ces scripts sont un candidat idéal à charger avec un modèle appelé 'lazy on load'. Cela signifie attendre l'événement load de la page et ensuite, pendant le temps d'inactivité, injecter le script.  Attendre le load assure même que le script ne concurrence pas la bande passante et le CPU  avec des ressources précoces plus importantes. Attendre un moment d'inactivité assure que le navigateur ne gère pas de tâches plus importantes comme l'entrée utilisateur.

Voici un exemple fonctionnel :

window.addEventListener("load", () => {
  window.requestIdleCallback(() => {
    const script = document.createElement("script");
    script.src = "/path/to/script.js";
    document.head.appendChild(script);
  });
});

Meilleures pratiques :

  • Chargez ces scripts en lazy load après que la page a chargé et attendez un moment d'inactivité.
  • Comprenez que les scripts chargés avec ce modèle ne sont pas garantis de charger vite

5. Scripts futurs

Les scripts futurs sont ceux qui ne seront pas nécessaires tant que des conditions spécifiques ne sont pas remplies. Par exemple, un script de paiement en plusieurs étapes devient pertinent seulement après qu'un utilisateur a ajouté des articles à son panier. Ces scripts peuvent souvent attendre beaucoup plus tard dans le parcours de l'utilisateur.

Jetez un coup d'œil à cet exemple. Il utilise l'intersection observer pour charger la logique JS requise pour le script d'inscription seulement lorsque le formulaire est dans le viewport visible.

<!DOCTYPE html>
<html>
  <head>
    <script>
      document.addEventListener("DOMContentLoaded", function () {
        const form = document.querySelector("form");
        const observer = new IntersectionObserver(function (entries) {
          entries.forEach((entry) => {
            if (entry.isIntersecting) {
              const script = document.createElement("script");
              script.src = "/sign-up.js";
              document.head.appendChild(script);
              observer.unobserve(form);
            }
          });
        });
        observer.observe(form);
      });
    </script>
  </head>
  <body>
    <form action="/sign-up" method="post">
      <label for="email">Email:</label>
      <input type="email" id="email" name="email" required />
      <button type="submit">Sign Up</button>
    </form>
  </body>
</html>

Meilleures pratiques :

  • Chargez ces scripts à la demande, déclenchés par des actions utilisateur.
  • Utilisez des techniques de code-splitting pour ne livrer que les parties requises à chaque étape.
  • Injectez-les dynamiquement seulement lorsque nécessaire, comme lorsqu'un utilisateur fait défiler vers une section spécifique.

Lab data is not enough.

I analyze your field data to find the edge cases failing your user experience.

Analyze My Data >>

  • Real User Data
  • Edge Case Detection
  • UX Focused
Optimiser la priorité JavaScript pour des chargements de page plus rapidesCore Web Vitals Optimiser la priorité JavaScript pour des chargements de page plus rapides