Javascript 使用下一个JS延迟脚本

Javascript 使用下一个JS延迟脚本,javascript,reactjs,next.js,Javascript,Reactjs,Next.js,我正在一个项目中使用NextJS,我正在使用Google的PageSpeedInsights工具进行一些优化。我的网站性能的主要负面因素之一是第三方脚本,主要是谷歌标签脚本(它也加载我的谷歌分析)和谷歌地图API脚本。到目前为止,我已经尝试了几种方法来抵消这两个库的加载,但我仍然从该工具中获得以下消息: 删除未使用的JavaScript https://maps.googleapis.com/maps/api/js?key=asdafsafasafasfasf&libraries=pla

我正在一个项目中使用NextJS,我正在使用Google的PageSpeedInsights工具进行一些优化。我的网站性能的主要负面因素之一是第三方脚本,主要是谷歌标签脚本(它也加载我的谷歌分析)和谷歌地图API脚本。到目前为止,我已经尝试了几种方法来抵消这两个库的加载,但我仍然从该工具中获得以下消息:

删除未使用的JavaScript

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)
我需要将这些脚本加载到站点的任何地方,因此我尝试延迟加载脚本,直到页面上的所有其他内容都加载完毕。以下是我最初拥有的:

\u 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>
    );
  }
}
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"
      />
    </>)
  }
}
然而,它仍然给我同样的错误信息。我不知道现在该试什么!是否有其他人遇到此问题并找到了解决方法


谢谢

我最近正在用更复杂的GTM配置处理同样的问题。我可以分享我的方法

首先,在Lighthouse中,“删除未使用的JavaScript”并不意味着不使用整个文件。它实际上只是告诉您,给定文件中有大量未使用的代码。如果是某个第三方文件,我们可能对此无能为力

此外,每个JavaScript文件(包括分析)都会对性能产生影响。理想情况下,只有在成本合理的情况下(基本分析、应用程序监控服务等…)才支付费用

目标

目标不是解决“删除未使用的JavaScript”。真正的目标应该是通过延迟加载JavaScript来减少JavaScript的影响,以便尽可能快地加载其他更重要的页面内容。

异步标记

GTM本身并没有很大的性能足迹。这实际上取决于GTM容器中的内容。我认为用
async
标记加载GTM是可以的

谷歌地图API可以通过GTM异步加载。我们可以更精确地决定何时加载它

GTM加载

对于不需要立即交付的脚本,例如Google Map API,您可能不希望将它们加载到加载的
容器上,因为这将占用宝贵的资源,可以用来加载真实的页面内容。您应该考虑将其移动到<代码>窗口加载。在这一点上,页面已经被完全加载,对谷歌网站核心Vita的影响应该是最小的

对于分析,理想情况下,应该尽早加载它们,以便更精确地捕获数据。但是,这可能会根据业务需求而改变。对于我的组织,我们将一些分析移到
窗口加载
阶段。原因是我们希望有更好的页面加载性能,并且我们并不真正关心在页面加载之前反弹的用户

如果需要进一步的延迟,我们可以创建一个额外的触发器,在超时几毫秒后触发。有关更多详细信息,请参阅此

潜在的解决方案

总之,这是一种我愿意采用的方法。这与我的团队在我们的项目中使用的类似

  • 仅使用
    async
    属性在
    Next.js
    中加载GTM
  • 将谷歌分析和谷歌地图API移至GTM
  • 在对业务/项目/用户仍有意义的情况下,尽可能延迟加载时间
我希望这是有意义的,是有益的

参考资料

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>
    );
  }
}
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"
      />
    </>)
  }
}

谷歌分析/Gtag

根据我自己的经验,我不得不遗憾地告诉你,延迟分析加载不是一个好主意,当调用一个不存在的函数时,常常会导致意外错误。所以最好在一开始就加载它,即使谷歌因为你使用他们自己的脚本而惩罚你,这很糟糕。因此,我认为您最初通过定制的document.js文件加载gtag的方法很好

谷歌地图

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>
    );
  }
}
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"
      />
    </>)
  }
}
感谢上帝,谷歌地图与众不同。有一个名为npm的包。这使得动态加载贴图成为可能,或者更容易。除此之外,您还可以利用JavaScript的功能。您可以创建一个自定义加载函数,该函数只能在满足某些条件后启动。它可能是这样的:

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
  }
};

您可以将其放置在
useffect
钩子中,甚至在用户悬停在某个位置或单击某个对象时调用它,从而将导入延迟更长时间。

我提供了此选项,因为它尚未出现在此处。这并不意味着这个解决方案是最好的。加载DOM内容后开始加载脚本的方法。我认为它可以插入\u document.js而不是上述三个脚本

我使用
setTimeout
将此任务放入事件队列,0表示它将尽快发生

<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)
      });
      `,
    }}
/>


如果我错了,请纠正我的错误,但是延迟脚本加载不会帮助您处理那些外部脚本中未使用的JavaScript。无论何时加载脚本,您仍然会使用相同的代码。在页面加载速度方面,我可以想象Google并不关心DOM加载完所有其他内容后加载的脚本,否?在这种情况下,您可能应该尝试使用
async
属性。我尝试了async,但不幸的是,它具有相同的效果。当尽早加载时,分析效果最好。此外,所有分析都会损害性能,因此这始终是一种折衷。这里重要的一点是,用户在每个域中加载此脚本一次。如果可能的话,您可以使用更轻的分析工具,比如Fathom