在 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 是否已預先載入:如要預覽網站,請按下「View App」,然後按下「Fullscreen」全螢幕

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

  3. 勾選「Disable cache」核取方塊。

  4. 請重新載入頁面。

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

開發人員工具「網路」分頁,其中醒目顯示 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.jsprefetch 設為 false

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

開發人員工具「網路」分頁,其中醒目顯示 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。在 /margherita 上,prefetch 屬性已設為 true/pineapple-pizza 上的 false

<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」會記錄「Build with Next.js.」的樂趣,並前往新的路徑:

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

結論

使用 <Link> 時,Next.js 會自動預先擷取轉譯連結網頁所需的 JavaScript,讓您更快前往新網頁。如果您使用的是自訂轉送,可以使用 Next.js 路由器 API 自行實作預先載入功能。為不常造訪的網頁停用預先載入功能,避免不必要地下載內容。