NextJS Core Web Vitals - 修复第三方脚本

终极 NextJS Core Web Vitals 指南 - 修复由第三方脚本引起的 Core Web Vitals 问题

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

修复 NextJS 中的第三方脚本

第三方脚本是为您的网站添加第三方功能的脚本。这些脚本通常由第三方托管,尽管这通常并非严格必要(例如,您可以自行托管分析 JavaScript 文件)。第三方脚本提供广泛的实用功能,使网页更加动态、互动和互联。这些脚本可能对您网站的功能或收入至关重要。但第三方脚本也带来许多风险,应加以考虑,以在提供价值的同时尽量减少其影响。

nextjs css network

试想一下:您是一个优化过的 Next.js 网站的自豪拥有者。您已经优化了所有代码,实现了某种形式的静态生成,优化了所有图片,实现了 Critical CSS,但您的网站仍然未能通过 Core Web Vitals。到底是怎么回事?

这可能是因为第三方脚本,例如广告、分析工具、社交媒体按钮、小部件、A/B 测试脚本、视频播放器等。

第三方脚本如何影响 Core Web Vitals

第三方脚本可能以超乎想象的方式破坏您的 Core Web Vitals。以下是我在实际网站上遇到的一些问题。

  • 拖慢网络速度。第三方脚本可能向多个服务器发送多个请求,下载未经优化的大型文件(如图片和视频),以及多次下载框架和库。
  • 第三方 JavaScript 可以在任何时候(甚至在一次页面访问中多次)阻塞 DOM,延迟页面的渲染速度,并占用过多的 CPU 时间,从而延迟用户交互并导致电池消耗。
  • 渲染阻塞的第三方脚本加载可能成为单点故障 (SPOF)
  • 第三方脚本可能因配置不当的 HTTP 缓存、缺乏足够的服务器压缩以及缓慢/过时的 HTTP 协议而导致网络问题
  • 以许多其他方式损害 user experience,例如隐藏内容、阻止浏览器事件(如 window load 事件)或使用过时的 API(如 document.write)

在 Next.js 中修复第三方脚本和 Core Web Vitals

理想情况下,您希望确保第三方脚本不会影响关键渲染路径。您的首选解决方案是使用 defer 或 async 属性。不幸的是,从时序角度来看,这对大多数 Next.js 网站来说并不是一个好的选择。Next.js 网站严重依赖 JavaScript 来水合页面。

这意味着一旦 Next.js 捆绑包下载完毕,浏览器就会运行该 JavaScript。这需要时间和资源。当浏览器忙于编译和运行第三方 JavaScript 时,这个过程会变慢。

介绍 Next.js Script 组件

Next.js Script 组件 next/script 是 HTML <script> 元素的扩展。它使开发者能够在应用程序的任何位置(next/head 之外)设置第三方脚本的加载优先级,在节省开发时间的同时提升加载性能。

要在应用程序中添加第三方脚本,请导入 next/script 组件:

import Script from 'next/script'

Strategy

使用 next/script,您可以通过 strategy 属性决定何时加载第三方脚本:

有三种不同的加载策略可供使用:

  • beforeInteractive:在页面可交互之前加载脚本
  • afterInteractive:在页面可交互之后立即加载脚本
  • lazyOnload:在空闲时间加载脚本
  • worker:在 web worker 中加载脚本

beforeInteractive 策略

使用 beforeInteractive 策略加载的脚本会从服务器注入到初始 HTML 中,并启用 defer 属性,在自身捆绑的 JavaScript 执行之前运行。

从 Core Web Vitals 的角度来看,这正是我们希望避免的行为!beforeInteractive 策略应仅用于对页面绝对关键的脚本。第三方脚本永远不应该是关键的!

<Script
  id="bootstrap-cdn"
  src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
  strategy="beforeInteractive"
 />

在这种情况下,bootstrap JavaScript 库被添加到生成的 HTML 中,并带有 defer 属性,位于 next.js 捆绑包之前。这意味着浏览器可能会在 next.js 捆绑包之前获取并执行 bootstrap 库。这将延迟 next.js 的水合,并且可能在浏览器应该下载和运行 next.js 代码块时阻塞主线程。对于 Core Web Vitals 来说,这意味着 First Input Delay 可能会受到影响。

afterInteractive 策略

使用 afterInteractive 策略的脚本在客户端注入,将在 Next.js 水合页面之后下载和执行。

从 Core Web Vitals 的角度来看,这是一个更好的(但尚未完美的)注入第三方脚本的位置。此策略应用于不需要尽快加载、可以在页面可交互后立即获取和执行的脚本。

<Script
  strategy="afterInteractive"
  dangerouslySetInnerHTML={{
    __html: `
    (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
    new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
    j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
    'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
    })(window,document,'script','dataLayer', 'GTM-XXXXXX');
  `,
  }}
/>

lazyOnload 策略

使用 lazyOnload 策略,事情终于变得有趣了!我对第三方脚本的看法很简单:"它们不应该对页面至关重要"。如果您离不开某个第三方脚本,那么您可能不应该依赖第三方。

使用 lazyOnload 策略的脚本在所有资源获取完毕后、空闲时间期间加载。这意味着第三方脚本不会干扰 next.js 代码块,并将最大程度减少该脚本对 First Input Delay (FID) 的影响。

<Script
  id="some-chat-script"
  src="https://example.com/chatscript.js"
  strategy="lazyOnload"
 />

worker 策略

worker 策略是一个实验性功能,使用 partytown https://partytown.builder.io/ 作为脚本和 web worker 之间的代理。这个概念很有趣,但目前可能还没有达到生产就绪状态,因为它仍处于测试阶段。我目前对 worker 策略的建议是暂时不要使用它,直到该项目成熟或 DOM 可供 web worker 使用。

Make decisions with Data.

You cannot optimize what you do not measure. Install the CoreDash pixel and capture 100% of user experiences.

Create Free Account >>

  • 100% Capture
  • Data Driven
  • Easy Install
NextJS Core Web Vitals - 修复第三方脚本Core Web Vitals NextJS Core Web Vitals - 修复第三方脚本