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

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

Milica Mihajlija
Milica Mihajlija

在這篇文章中,您將瞭解 Next.js 的路由運作方式、如何提升速度,以及如何自訂路由以滿足需求。

Next.js 中,您不必手動設定路徑。 Next.js 使用檔案系統轉送,因此您只需在 ./pages/ 目錄中建立檔案和資料夾:

包含三個檔案的頁面目錄:index.js、margherita.js 和 pineapple-pizza.js。

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

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

使用 <Link> 元件進行導覽時,Next.js 會為您多做一些事。一般來說,您點選連結後,系統就會下載網頁,但 Next.js 會自動預先擷取轉譯網頁所需的 JavaScript。

載入含有幾個連結的網頁時,您點選連結時,連結背後的元件可能已經擷取完畢。這項功能可加快導覽至新網頁的速度,進而提升應用程式的回應速度。

在範例應用程式中,index.js 頁面會連結至 margherita.js,並使用 <Link>

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

  1. 開啟 Chrome 開發人員工具
  2. 按一下 [網路] 分頁標籤。
  3. 勾選「停用快取」核取方塊。
  4. 請重新載入頁面。

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

DevTools 的「網路」分頁,並醒目顯示 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 設為 <Link>

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

DevTools 的「網路」分頁,並醒目顯示 margherita.js。

使用自訂路徑預先擷取

<Link> 元件適用於大多數用途,但您也可以建構自己的元件來執行路由作業。Next.js 提供 next/router 中提供的路由器 API,讓您更輕鬆地完成這項工作。如要在導覽至新路徑前執行某些動作 (例如提交表單),可以在自訂轉送程式碼中定義該動作。

使用自訂元件進行轉送時,也可以為這些元件新增預先擷取功能。 如要在路由程式碼中實作預先擷取功能,請使用 useRouter 中的 prefetch 方法。

請參閱這個範例應用程式中的 components/MyLink.js

預先擷取作業是在 useEffect Hook 內完成。如果 <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.jsprefetch 屬性在 /margherita 上設為 true,在 /pineapple-pizza 上則設為 false

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

載入 index.js 時,「網路」分頁會顯示 margherita.js 已下載,但 pineapple-pizza.js 未下載:

DevTools 的「網路」分頁,並醒目顯示 margherita.js。

點選任一連結後,控制台會記錄「Having fun with Next.js.」,並前往新路徑:

開發人員工具控制台顯示「Having fun with Next.js.」訊息。

結論

使用 <Link> 時,Next.js 會自動預先擷取轉譯連結網頁所需的 JavaScript,因此導向新網頁的速度會更快。如果您使用自訂路徑,可以透過 Next.js 路由器 API 自行實作預先擷取功能。停用很少造訪網頁的預先擷取功能,避免不必要地下載內容。