用於管理第三方程式庫的 Next.js 套件

2021 年,Chrome Aurora 團隊推出了指令碼元件,以改善 Next.js 中第三方指令碼的載入效能。自推出以來,我們已擴充這項功能,讓開發人員能更輕鬆快速地載入第三方資源。

這篇網誌文章將概略說明我們推出的新功能,其中最值得注意的是 @next/third-parties 程式庫,以及我們未來的路線圖計畫。

第三方指令碼對成效的影響

在 Next.js 網站中,41% 的第三方要求都是指令碼。與其他內容類型不同,指令碼的下載和執行作業可能需要相當長的時間,這可能會阻斷轉譯作業,並延遲使用者互動。Chrome 使用者體驗報告 (CrUX) 的資料顯示,載入更多第三方指令碼的 Next.js 網站,其Interaction to Next Paint (INP)Largest Contentful Paint (LCP) 通過率較低。

長條圖:顯示 Next.js 取得良好 INP 和 LCP 分數的百分比,與載入的第三方數量成反比
2023 年 12 月 CrUX 報告 (110,823 個網站)

這張圖表顯示的關聯性並不代表因果關係。不過,本機實驗提供了額外證據,證明第三方指令碼會對網頁效能造成重大影響。舉例來說,下方圖表比較了各種實驗室指標,當 Google 代碼管理工具容器 (包含 18 個隨機選取的代碼) 新增至 Taxonomy (熱門的 Next.js 範例應用程式) 時。

長條圖:顯示網站在載入時,使用和未使用 Google 代碼管理工具時的各種實驗室指標差異
WebPageTest (行動裝置 4G - 美國維吉尼亞州)

如要進一步瞭解這些時間的測量方式,請參閱 WebPageTest 說明文件。一眼望去,您會發現所有實驗室指標都受到 Google 代碼管理工具容器的影響。舉例來說,總封鎖時間 (TBT) 是實驗室中用於模擬 INP 的實用代理值,其值增加了近 20 倍。

指令碼元件

在 Next.js 中發布 <Script> 元件時,我們確保透過易於使用且與傳統 <script> 元素相似的 API 引入該元件。開發人員可以使用此功能,在應用程式的任何元件中並置第三方指令碼,Next.js 會在載入重要資源後負責安排指令碼的順序。

<!-- By default, script will load after page becomes interactive -->
<Script src="https://example.com/sample.js" />

<!-- Script is injected server-side and fetched before any page hydration occurs -->
<Script strategy=”beforeInteractive” src="https://example.com/sample.js" />

<!-- Script is fetched later during browser idle time -->
<Script strategy=”lazyOnload” src="https://example.com/sample.js" />

成千上萬的 Next.js 應用程式都使用 <Script> 元件,包括 PatreonTargetNotion 等熱門網站。雖然這項功能相當實用,但部分開發人員對以下事項提出疑慮:

  • 在 Next.js 應用程式中放置 <Script> 元件的正確位置,並遵循不同第三方供應商的各種安裝說明 (開發人員體驗)
  • 哪種載入策略最適合用於不同的第三方指令碼(使用者體驗)

為解決這兩項疑慮,我們推出了 @next/third-parties,這是一款專用程式庫,提供一組經過最佳化的元件和公用程式,可針對熱門的第三方服務進行客製化。

開發人員體驗:讓第三方程式庫更容易管理

許多 Next.js 網站都使用許多第三方指令碼,其中 Google 代碼管理工具最受歡迎,66% 的網站都使用@next/third-parties 會在 <Script> 元件上進行建構,藉由引入高階包裝函式,簡化這些常見用途的使用方式。

import { GoogleAnalytics } from "@next/third-parties/google";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
      <GoogleTagManager gtmId="GTM-XYZ" />
    </html>
  );
}

Google Analytics 是另一個廣泛使用的第三方指令碼 (Next.js 網站的 52%),也有專屬的元件。

import { GoogleAnalytics } from "@next/third-parties/google";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
      <GoogleAnalytics gaId="G-XYZ" />
    </html>
  );
}

@next/third-parties 不僅可簡化常用指令碼的載入程序,還可讓我們為其他第三方類別 (例如嵌入) 開發公用程式。舉例來說,Google 地圖和 YouTube 嵌入項目分別用於 8%4% 的 Next.js 網站,我們也已推出元件,方便您載入這些項目。

import { GoogleMapsEmbed } from "@next/third-parties/google";
import { YouTubeEmbed } from "@next/third-parties/google";

export default function Page() {
  return (
    <>
      <GoogleMapsEmbed
        apiKey="XYZ"
        height={200}
        width="100%"
        mode="place"
        q="Brooklyn+Bridge,New+York,NY"
      />
      <YouTubeEmbed videoid="ogfYd705cRs" height={400} params="controls=0" />
    </>
  );
}

使用者體驗:加快第三方程式庫的載入速度

在理想情況下,每個廣泛採用的第三方程式庫都會經過充分最佳化,因此不需要任何可改善效能的抽象層。不過,在這個目標實現之前,我們可以透過 Next.js 等熱門架構整合,改善使用者體驗。我們可以嘗試使用不同的載入技術,確保指令碼以正確方式排序,並最終與第三方供應商分享意見回饋,鼓勵上游變更。

以嵌入的 YouTube 影片為例,某些替代實作項目的成效遠優於原生嵌入項目。目前,由 @next/third-parties 匯出的 <YouTubeEmbed> 元件會使用 lite-youtube-embed,在「Hello, World」Next.js 比較中,這項元件可大幅加快載入速度。

GIF 顯示 YouTube 嵌入元件與一般 YouTube iframe 的網頁載入比較結果
WebPageTest (行動裝置 4G - 美國維吉尼亞州)

同樣地,對於 Google 地圖,我們會將 loading="lazy" 納入內嵌的預設屬性,確保地圖只在距離可視區域一定距離時載入。這似乎是顯而易見的屬性,尤其是 Google 地圖說明文件在範例程式碼片段中加入了這個屬性,但只有45% 的 Next.js 網站使用 loading="lazy" 嵌入 Google 地圖。

在網路工作站中執行第三方指令碼

我們在 @next/third-parties 中探索的一種進階技巧,是讓第三方指令碼更容易卸載至網路工作者。Partytown 等程式庫廣泛採用這種做法,可將第三方指令碼對網頁效能的影響降到最低,方法是將指令碼完全重新配置至主執行緒之外。

下列 GIF 動畫顯示在 Next.js 網站中,將不同 <Script> 策略套用至 GTM 容器時,長時間工作和主執行緒封鎖時間的變化。請注意,雖然切換策略選項只會延遲這些指令碼的執行時間,但將這些指令碼重新指派至網路工作者,就能完全消除它們在主執行緒上執行的時間。

這張 GIF 顯示不同 Script 策略的主要執行緒封鎖時間差異
WebPageTest (行動裝置 4G - 美國維吉尼亞州)

在這個特定範例中,將 GTM 容器及其相關聯的代碼指令碼執行作業移至網頁工作者,可將 TBT 縮短 92%

值得注意的是,如果沒有妥善管理,這項技巧可能會悄悄破壞許多第三方指令碼,導致難以進行偵錯。在未來幾個月內,我們會驗證 @next/third-parties 提供的任何第三方元件在網頁工作者中執行時是否正常運作。如果是的話,我們會努力提供簡單的選用方式,讓開發人員使用這項技術。

後續步驟

在開發這個套件時,我們發現需要將第三方載入最佳化建議集中管理,以便其他架構也能從相同的基礎技術中受益。因此,我們建構了 Third Party Capital,這是一個使用 JSON 描述第三方載入技術的程式庫,目前是 @next/third-parties 的基礎。

接下來,我們將持續專注於改善 Next.js 提供的元件,並擴大努力,在其他熱門架構和 CMS 平台中納入類似的實用工具。我們目前正與 Nuxt 維護人員合作,並計劃在不久後發布類似的第三方公用程式,以便針對他們的生態系統進行客製化。

如果您在 Next.js 應用程式中使用的第三方服務支援 @next/third-parties,請安裝套件並試試看!歡迎在 GitHub 上提供意見。