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

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

這篇網誌文章概略介紹我們已發布的最新功能,最主要的是 @next/third-parties 程式庫,以及我們未來計畫的藍圖。

第三方指令碼的成效影響

在 Next.js 網站中,41% 的第三方要求都是指令碼。有別於其他內容類型,指令碼可能需要大量下載及執行時間,因而阻擋轉譯及延遲使用者互動。Chrome 使用者體驗報告 (CrUX) 的資料顯示,載入更多第三方指令碼的 Next.js 網站,其Interaction to Next Paint (INP)最大內容繪製 (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 顯示不同指令碼策略在主執行緒封鎖時間上的差異
WebPageTest (行動裝置 4G - 美國維吉尼亞州)

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

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

後續步驟

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

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

如果 @next/third-parties 支援您在 Next.js 應用程式中使用的其中一個第三方,請安裝套件並試試看!歡迎前往 GitHub 與我們分享您的意見回饋。