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

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

這篇網誌文章概述了我們發布的最新功能 (尤其是 @next/third-parties 程式庫),以及目前藍圖中未來計畫的概述。

第三方指令碼效能的影響

Next.js 網站上有 41% 的第三方要求屬於指令碼。與其他類型的內容類型不同,指令碼可能需要大量的下載和執行時間,可能會阻礙轉譯並延遲使用者互動時間。根據 Chrome 使用者體驗報告 (CrUX) 的資料顯示,在載入更多第三方指令碼的 Next.js 網站上,與下一個繪製 (INP) 的互動 (INP)最大內容繪製 (LCP) 通過率會較低。

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

本圖表觀察到的相關性,並不代表因果關係。但是,本機實驗提供了額外的證據,證明第三方指令碼會大幅影響網頁效能。舉例來說,下方圖表比較了 Google 代碼管理工具容器 (包括 18 個隨機選取的標記) 新增到熱門 Next.js 範例應用程式的 Taxonomy 後,會發現的各種研究室指標。

這張長條圖顯示網站在載入時與未使用 Google 代碼管理工具時,各種研究室指標的差異
WebPageTest (Mobile 4G - 維吉尼亞州)

WebPageTest 說明文件詳細說明瞭這些時間的評估方式。一眼就能瞭解,所有研究室指標都受到 GTM 容器的影響。像是總封鎖時間 (TBT) 這類實用的研究室 Proxy,近乎使用 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 應用程式 (包括 PatreonTargetNotion 等熱門網站) 使用 <Script> 元件。儘管效率高,部分開發人員仍對下列幾點有所疑慮:

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

為解決這兩項疑慮,我們推出 @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 可以簡化載入常用指令碼的程序,但同時也擴展了我們開發其他第三方類別 (例如嵌入) 公用程式的能力。舉例來說,Next.js 網站分別有 8%4% 使用 Google 地圖和 YouTube 嵌入內容,而我們也推出了元件,讓兩者更容易載入。

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 (Mobile 4G - 維吉尼亞州)

以 Google 地圖來說,我們也會納入 loading="lazy" 做為嵌入項目的預設屬性,確保地圖只有在與可視區域有特定距離時才會載入。這似乎顯然顯而易見 (尤其是在 Google 地圖說明文件的程式碼片段中),但只有 45% 的 Next.js 網站使用 loading="lazy"

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

我們正在 @next/third-parties 中探索的其中一項進階技術,是更輕鬆地將第三方指令碼卸載至網路工作站。而第三方指令碼則受到 Partytown 等程式庫熱門的喜愛,可藉由將第三方指令碼完全從主執行緒重新分配,大幅降低對網頁效能的影響。

以下 GIF 動畫呈現了在 Next.js 網站上對 GTM 容器套用不同 <Script> 策略時,長時間工作和主要執行緒阻斷時間的變化。請注意,雖然切換策略選項只會延遲指令碼執行的時間,但將這些指令碼重新分配給網路工作站可以完全省去主執行緒上的作業。

GIF:顯示不同指令碼策略在主執行緒封鎖時間的差異
WebPageTest (Mobile 4G - 維吉尼亞州)

在這個特定範例中,將 GTM 容器及其相關標記指令碼的執行作業移至網路工作站,讓 TBT 量減少了 92%

值得注意的是,如未謹慎管理,這項技術可能會不通知任何第三方指令碼,導致偵錯作業變得困難。在接下來的幾個月,我們將驗證 @next/third-parties 在網路工作站中執行時,提供的任何第三方元件是否正常運作。如果是的話,我們將致力提供方便開發人員使用這項技巧的簡易選用方法。

後續步驟

在開發這個套件的過程中,發現必須集中管理第三方載入建議,這樣其他架構也能受益於相同的基礎技術。這促使我們打造了第三方資本,這是使用 JSON 描述第三方載入技術的程式庫,目前是 @next/third-parties 的基礎。

往後,我們將繼續專注於改善 Next.js 提供的元件,並擴大處理範圍,將類似的公用程式納入其他熱門架構和 CMS 平台。我們目前正與 Nuxt 維護人員合作,計劃在不久後推出專為自家生態系統打造的類似第三方公用程式。

如果 @next/third-parties 支援您在 Next.js 應用程式中使用的第三方,請安裝套件並試著拍攝!我們很樂意聆聽您對 GitHub 的意見。