2021 年,Chrome Aurora 團隊推出了指令碼元件,以改善 Next.js 中第三方指令碼的載入效能。自推出以來,我們已擴充這項功能,讓開發人員能更輕鬆快速地載入第三方資源。
這篇網誌文章將概略說明我們推出的新功能,其中最值得注意的是 @next/third-parties 程式庫,以及我們未來的路線圖計畫。
第三方指令碼對成效的影響
在 Next.js 網站中,41% 的第三方要求都是指令碼。與其他內容類型不同,指令碼的下載和執行作業可能需要相當長的時間,這可能會阻斷轉譯作業,並延遲使用者互動。Chrome 使用者體驗報告 (CrUX) 的資料顯示,載入更多第三方指令碼的 Next.js 網站,其Interaction to Next Paint (INP) 和 Largest Contentful Paint (LCP) 通過率較低。
這張圖表顯示的關聯性並不代表因果關係。不過,本機實驗提供了額外證據,證明第三方指令碼會對網頁效能造成重大影響。舉例來說,下方圖表比較了各種實驗室指標,當 Google 代碼管理工具容器 (包含 18 個隨機選取的代碼) 新增至 Taxonomy (熱門的 Next.js 範例應用程式) 時。
如要進一步瞭解這些時間的測量方式,請參閱 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>
元件,包括 Patreon、Target 和 Notion 等熱門網站。雖然這項功能相當實用,但部分開發人員對以下事項提出疑慮:
- 在 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 比較中,這項元件可大幅加快載入速度。
同樣地,對於 Google 地圖,我們會將 loading="lazy"
納入內嵌的預設屬性,確保地圖只在距離可視區域一定距離時載入。這似乎是顯而易見的屬性,尤其是 Google 地圖說明文件在範例程式碼片段中加入了這個屬性,但只有45% 的 Next.js 網站使用 loading="lazy"
嵌入 Google 地圖。
在網路工作站中執行第三方指令碼
我們在 @next/third-parties
中探索的一種進階技巧,是讓第三方指令碼更容易卸載至網路工作者。Partytown 等程式庫廣泛採用這種做法,可將第三方指令碼對網頁效能的影響降到最低,方法是將指令碼完全重新配置至主執行緒之外。
下列 GIF 動畫顯示在 Next.js 網站中,將不同 <Script>
策略套用至 GTM 容器時,長時間工作和主執行緒封鎖時間的變化。請注意,雖然切換策略選項只會延遲這些指令碼的執行時間,但將這些指令碼重新指派至網路工作者,就能完全消除它們在主執行緒上執行的時間。
在這個特定範例中,將 GTM 容器及其相關聯的代碼指令碼執行作業移至網頁工作者,可將 TBT 縮短 92%。
值得注意的是,如果沒有妥善管理,這項技巧可能會悄悄破壞許多第三方指令碼,導致難以進行偵錯。在未來幾個月內,我們會驗證 @next/third-parties
提供的任何第三方元件在網頁工作者中執行時是否正常運作。如果是的話,我們會努力提供簡單的選用方式,讓開發人員使用這項技術。
後續步驟
在開發這個套件時,我們發現需要將第三方載入最佳化建議集中管理,以便其他架構也能從相同的基礎技術中受益。因此,我們建構了 Third Party Capital,這是一個使用 JSON 描述第三方載入技術的程式庫,目前是 @next/third-parties
的基礎。
接下來,我們將持續專注於改善 Next.js 提供的元件,並擴大努力,在其他熱門架構和 CMS 平台中納入類似的實用工具。我們目前正與 Nuxt 維護人員合作,並計劃在不久後發布類似的第三方公用程式,以便針對他們的生態系統進行客製化。
如果您在 Next.js 應用程式中使用的第三方服務支援 @next/third-parties
,請安裝套件並試試看!歡迎在 GitHub 上提供意見。