7 votes

Report des scripts avec le prochain JS

J'utilise Next JS sur un projet et je procède à quelques optimisations à l'aide de l'outil Page Speed Insights de Google. L'un des principaux contributeurs négatifs aux performances de mes sites est les scripts tiers, principalement Google Tag scripts (qui charge également mon Google Analytics) et l'API Google maps scripts. Jusqu'à présent, j'ai essayé plusieurs choses pour compenser le chargement de ces deux bibliothèques, mais je reçois toujours les messages suivants de l'outil :

Supprimez les JavaScript inutilisés

https://maps.googleapis.com/maps/api/js?key=asdafsafasafasfasf&libraries=places&language=en&region=US
(maps.googleapis.com)

https://www.googletagmanager.com/gtag/js?id=UA-123123-2
(www.googletagmanager.com)

J'ai besoin que ces scripts soient chargés partout sur le site, j'ai donc essayé de retarder le chargement des scripts jusqu'à ce que tout le reste de la page ait fini de se charger. Voici ce que j'avais initialement :

_document.js

import Document, { Head, Main, NextScript, Html } from "next/document";

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx);
    return { ...initialProps };
  }

  render() {
    return (
      <Html lang="en">
        <Head>
          <script
            defer
            src={`https://www.googletagmanager.com/gtag/js?id=UA-123123-2`}
          />
          <script
            defer
            src="https://maps.googleapis.com/maps/api/js?key=asdafsafasafasfasf&libraries=places&language=en&region=US"
          />
          <script
            dangerouslySetInnerHTML={{
              __html: `
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
            gtag('js', new Date());
            gtag('config', 'UA-123123-2');
          `,
            }}
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

Comme vous pouvez le voir, je charge simplement les scripts avec la balise defer prop comme vous le feriez normalement. Avec cette méthode, google page speed insights me donne toujours le même message cependant. J'ai alors essayé une approche différente en utilisant un composant expérimental dans Next JS appelé ScriptLoader qui vise à permettre aux gens de différer les scripts. Voici un lien vers ce composant :

https://github.com/vercel/next.js/discussions/18172

Voici ma mise en œuvre :

_app.js

import App from "next/app";
import ScriptLoader from "next/dist/client/experimental-script.js";

export default class NextApp extends App {
  render() {
    return (<>
      <ScriptLoader
        strategy="defer"
        src="https://www.googletagmanager.com/gtag/js?id=UA-123123-2"
      />
      <ScriptLoader
        strategy="defer"
        src="https://maps.googleapis.com/maps/api/js?key=asdafsafasafasfasf&libraries=places&language=en&region=US"
      />
    </>)
  }
}

Cependant, le message d'erreur reste le même. Je ne sais pas quoi essayer maintenant ! Quelqu'un d'autre a-t-il rencontré ce problème et trouvé une solution de contournement ?

Merci

5voto

Gh05d Points 155

Google Analytics / Gtag

De ma propre expérience, je dois malheureusement vous dire que différer le chargement de l'analytique n'est pas une bonne idée et conduit souvent à des erreurs inattendues lorsqu'on appelle une fonction qui n'existe pas (encore). Donc, mieux vaut charger cela au tout début, même si cela craint que Google vous pénalise pour avoir utilisé leurs propres scripts. Donc je pense que votre approche initiale avec le chargement gtag par l'intermédiaire d'un _document.js est bien.

Google Maps

Dieu merci, c'est différent pour Google Maps . Il existe un paquet npm appelé Chargeur API JavaScript de Google Maps . Il est ainsi possible - ou plus facile - de charger Cartes de manière dynamique. En outre, vous pouvez tirer parti de l'option fonctionnalité d'importation dynamique de JavaScript . Vous pourriez créer une fonction de chargement personnalisée qui ne se déclenche qu'une fois certaines conditions remplies. Cela pourrait ressembler à ceci :

const myCustomLoadFunction = async () => {
  try {
    const { Loader } = await import("@googlemaps/js-api-loader");
    const loader = new Loader({
      apiKey: "YOUR_API_KEY",
      version: "weekly",
      // ...additionalOptions,
    });

    const mapOptions = {
      center: { lat: 0, lng: 0 },
      zoom: 4,
    };

    await loader.load();
    new google.maps.Map(document.getElementById("map"), mapOptions);
  } catch (e) {
    // do something
  }
};

Vous pourriez le placer dans un useEffect ou même l'appeler lorsqu'un utilisateur survole un endroit ou clique sur un élément et ainsi retarder encore plus l'importation.

2voto

Andrew Zheng Points 1199

Je suis confronté au même problème récemment avec une configuration GTM plus complexe. Je peux partager mes approches.

Tout d'abord, dans Lighthouse, l'option "Supprimer le JavaScript inutilisé" n'a PAS signifie que le fichier entier n'est pas utilisé. Cela vous indique simplement qu'il y a une grande partie de code inutilisé dans un fichier donné. S'il s'agit d'un fichier tiers, nous ne pourrons peut-être rien y faire.

En outre, chaque fichier JavaScript, y compris les analyses, aura un impact sur les performances. Idéalement, ne payez le prix que lorsque le coût peut être justifié (analyses essentielles, service de surveillance des applications, etc...).

Objectif

L'objectif n'est pas de résoudre le problème "Supprimer le JavaScript inutilisé". Le véritable objectif devrait être de réduire l'impact des JavaScript en reportant leur chargement afin que d'autres contenus de page plus importants puissent être chargés aussi rapidement que possible.

Balise asynchrone

Le GTM lui-même n'a pas une grande empreinte sur les performances. Cela dépend vraiment de ce que vous avez dans votre conteneur GTM. Je pense qu'avoir GTM chargé avec async est bien.

L'API Google Maps peut être chargée de manière asynchrone par GTM. Nous pouvons décider du moment de son chargement de manière plus précise.

Chargement GTM

Pour les scripts que vous n'avez pas besoin de livrer immédiatement, tels que l'API Google Map, vous ne voulez probablement pas les charger sur Container Loaded car cela prend des ressources précieuses qui peuvent être utilisées pour charger le contenu réel de la page. Vous devriez envisager de le déplacer vers Window Loaded . À ce stade, la page a été entièrement chargée et l'impact sur Google Web Core Vita devrait être minimal.

Pour les analyses, l'idéal est de les charger le plus tôt possible afin de capturer des données plus précises. Toutefois, cela peut changer en fonction des besoins de l'entreprise. Dans mon organisation, nous déplaçons certaines analyses à Window Loaded phase. La raison en est que nous voulons obtenir de meilleures performances de chargement des pages et que nous ne nous soucions pas vraiment des utilisateurs qui rebondissent avant même que la page ne soit chargée.

Si l'on souhaite un délai supplémentaire, on peut créer un déclencheur supplémentaire qui se déclenche après quelques ms de délai. Pour plus de détails, vous pouvez vous référer à ceci article de blog

Une solution potentielle

En résumé, c'est une approche que je choisirais. Elle est similaire à celle que mon équipe utilise pour nos projets.

  • Ne chargez le GTM que dans Next.js avec le async attribut.
  • Déplacer les API Google Analytic et Google Map vers GTM
  • Retardez le temps de chargement autant que possible tout en conservant un sens pour l'entreprise/le projet/l'utilisateur.

J'espère que cela a du sens et est utile.

Références

GTM - Déclencheur de la vue de la page

2voto

Daniil Loban Points 2371

Je propose cette option car elle n'a pas encore été proposée. Cela ne signifie pas que cette solution soit la meilleure. . Un moyen de lancer le chargement du script après le chargement du contenu du DOM. Je pense que cela peut être inséré dans _document.js au lieu des trois scripts mentionnés ci-dessus.

J'utilise setTimeout pour mettre cette tâche dans la file d'attente des événements, 0 signifie qu'elle se produira aussi rapidement que possible.

<script 
    dangerouslySetInnerHTML={{
      __html: `
      document.addEventListener("DOMContentLoaded", function(event) {
        setTimeout(function() {
            var gtag = document.createElement('script');
            gtag.type = 'text/javascript';
            gtag.async = true;
            var gmaps = gtag.cloneNode(false);
            gtag.src = "https://www.googletagmanager.com/gtag/js?id=UA-123123-2"
            gmaps.src = "https://maps.googleapis.com/maps/api/js?key=asdafsafasafasfasf&libraries=places&language=en&region=US"

            var s = document.getElementsByTagName('script')[0]; 
            s.parentNode.insertBefore(gtag, s);
            s.parentNode.insertBefore(gmaps, s);            

            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
            gtag('js', new Date());
            gtag('config', 'UA-123123-2');
        }, 0)
      });
      `,
    }}
/>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X