2021 年,Chrome Aurora 團隊推出了指令碼元件,以改善 Next.js 中第三方指令碼的載入效能。自推出以來,我們已擴充這項功能,讓開發人員能更輕鬆快速地載入第三方資源。
這篇網誌文章概略介紹我們已發布的最新功能,最主要的是 @next/third-parties 程式庫,以及我們未來計畫的藍圖。
第三方指令碼的成效影響
在 Next.js 網站中,41% 的第三方要求都是指令碼。有別於其他內容類型,指令碼可能需要大量下載及執行時間,因而阻擋轉譯及延遲使用者互動。Chrome 使用者體驗報告 (CrUX) 的資料顯示,載入更多第三方指令碼的 Next.js 網站,其Interaction to Next Paint (INP) 和最大內容繪製 (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/third-parties
支援您在 Next.js 應用程式中使用的其中一個第三方,請安裝套件並試試看!歡迎前往 GitHub 與我們分享您的意見回饋。