在 Next.js 中使用預先擷取路徑

Next.js 如何透過預先擷取路徑功能加快瀏覽速度,以及如何自訂這項功能。

米莉卡.米哈吉利亞 (Milica Mihajlija)
Milica Mihajlija

您會學到什麼?

在這篇文章中,您會瞭解 Next.js 轉送功能的運作方式、如何針對速度進行最佳化調整,以及如何根據需求進行自訂。

Next.js,您不必手動設定轉送功能。Next.js 使用以檔案系統為基礎的轉送機制,因此您只需在 ./pages/ 目錄中建立檔案和資料夾:

含有三個檔案的網頁目錄螢幕截圖:index.js、margherita.js 和 pineapple-披薩.js。

如要連結至不同頁面,請使用 <Link> 元件,方法與使用舊的 <a> 元素類似:

<Link href="/margherita">
  <a>Margherita</a>
</Link>

使用 <Link> 元件進行導覽時,Next.js 會稍加為您一些。通常,當您點選網頁連結時即可下載檔案,但 Next.js 會自動預先擷取轉譯網頁所需的 JavaScript。

當您載入含有一些連結的頁面時,很有可能是因為在您點選連結時,系統已擷取其背後的元件。這樣可加快導覽至新頁面的速度,從而改善應用程式的回應速度。

在下方的範例應用程式中,index.js 頁面會透過 <Link> 連結至 margherita.js

使用 Chrome 開發人員工具驗證 margherita.js 是否已預先擷取: 1. 如要預覽網站,請按下「查看應用程式」,然後按下「全螢幕」圖示 全螢幕

  1. 按下 `Control+Shift+J 鍵 (在 Mac 上為 Command+Option+J 鍵) 開啟開發人員工具。
  2. 按一下 [網路] 分頁標籤。

  3. 勾選「停用快取」核取方塊。

  4. 重新載入網頁。

載入 index.js 時,「Network」分頁也會顯示已下載 margherita.js

開發人員工具「Network」分頁,特別標出 margherita.js。

自動預先擷取的運作方式

Next.js 預先擷取只會顯示在可視區域中的連結,並使用 Intersection Observer API 偵測這些連結。此外,當網路連線速度緩慢或使用者已啟用 Save-Data 時,這項功能也會停用預先擷取功能。根據這些檢查,Next.js 會動態插入 <link rel="preload"> 標記以下載元件,以供後續導覽使用。

Next.js 只會「擷取」JavaScript,不會執行。如此一來,在您造訪連結之前,系統都不會下載預先擷取頁面可能要求的任何其他內容。

避免進行不必要的預先擷取

為了避免下載不必要的內容,您可以將 <Link> 上的 prefetch 屬性設為 false,針對很少造訪的網頁停用預先擷取功能:

<Link href="/pineapple-pizza" prefetch={false}>
  <a>Pineapple pizza</a>
</Link>

在第二個範例應用程式中,index.js 頁面有將 <Link> 設為 pineapple-pizza.js,並將 prefetch 設為 false

如要檢查網路活動,請按照第一個範例中的步驟進行。載入 index.js 時,開發人員工具的「Network」分頁會顯示已下載 margherita.js,但 pineapple-pizza.js 不會:

開發人員工具「Network」分頁,特別標出 margherita.js。

使用自訂轉送進行預先擷取

<Link> 元件適用於大部分用途,但您也可以建構自己的元件來執行轉送。Next.js 可讓您使用 next/router 中的 Router API,輕鬆執行這項作業。如要在前往新路徑之前執行特定操作 (例如提交表單),可以在自訂轉送程式碼中定義。

使用自訂元件進行轉送時,也可以為這些元件加入預先擷取功能。如要在轉送程式碼中實作預先擷取功能,請使用 useRouterprefetch 方法。

請查看範例應用程式中的 components/MyLink.js

預先擷取作業會在 useEffect 掛鉤中完成。如果 <MyLink> 上的 prefetch 屬性設為 true,系統會在轉譯 <MyLink> 時預先擷取 href 屬性中指定的路徑:

useEffect(() => {
    if (prefetch) router.prefetch(href)
});

點選連結後,轉送作業就會在 handleClick 中完成。系統會將訊息記錄至主控台,push 方法會前往 href 中指定的新路徑:

const handleClick = e => {
    e.preventDefault();
    console.log("Having fun with Next.js.");
    router.push(href);
};

在這個範例應用程式中,index.js 頁面有 <MyLink>margherita.jspineapple-pizza.js/margheritaprefetch 屬性設為 true/pineapple-pizzafalse

<MyLink href="/margherita" title="Margherita" prefetch={true} />
<MyLink href="/pineapple-pizza"  title="Pineapple pizza" prefetch={false} />

載入 index.js 時,「Network」分頁會顯示已下載 margherita.js,且 pineapple-pizza.js 不會:

開發人員工具「Network」分頁,特別標出 margherita.js。

當您按一下任一連結時,Console 就會記錄「Hasving with Next.js.」並瀏覽至新的路徑:

開發人員工具控制台顯示「享受 Next.js 樂趣」的訊息。

結語

使用 <Link> 時,Next.js 會自動預先擷取轉譯連結網頁所需的 JavaScript,加快導覽至新網頁的速度。如果您使用自訂轉送,則可使用 Next.js 路由器 API 自行實作預先擷取。停用針對極少造訪的網頁停用預先擷取功能,避免下載不必要的內容。