連結與導航
在 Next.js 中有四種方式可以在路由之間進行導航:
- 使用
<Link>
元件 - 使用
useRouter
鉤子 (客戶端元件) - 使用
redirect
函式 (伺服器元件) - 使用原生的 History API
本頁將介紹如何使用這些選項,並深入探討導航的運作原理。
<Link>
元件
<Link>
是一個內建元件,它擴展了 HTML 的 <a>
標籤,提供 預取 (prefetching) 和客戶端路由導航功能。這是 Next.js 中推薦的主要路由導航方式。
您可以從 next/link
導入它,並向元件傳遞 href
屬性:
您還可以傳遞其他可選屬性給 <Link>
。詳見 API 參考文件。
useRouter()
鉤子
useRouter
鉤子允許您從 客戶端元件 中以程式方式變更路由。
完整的 useRouter
方法列表,請參閱 API 參考文件。
建議: 除非有特殊需求需要使用
useRouter
,否則建議使用<Link>
元件進行路由導航。
redirect
函式
對於 伺服器元件,請改用 redirect
函式。
重要須知:
redirect
預設返回 307 (臨時重定向) 狀態碼。在伺服器動作 (Server Action) 中使用時,它會返回 303 (查看其他),這通常用於在 POST 請求後重定向到成功頁面。redirect
內部會拋出錯誤,因此應在try/catch
區塊外呼叫。redirect
可以在客戶端元件的渲染過程中被呼叫,但不能在事件處理程序中呼叫。這種情況下應改用useRouter
鉤子。redirect
也接受絕對 URL,可用於重定向到外部連結。- 如果您希望在渲染過程之前進行重定向,請使用
next.config.js
或 中介軟體 (Middleware)。
更多資訊請參閱 redirect
API 參考文件。
使用原生 History API
Next.js 允許您使用原生的 window.history.pushState
和 window.history.replaceState
方法來更新瀏覽器的歷史記錄堆疊,而無需重新載入頁面。
pushState
和 replaceState
的呼叫會與 Next.js 路由器整合,使您可以與 usePathname
和 useSearchParams
同步。
window.history.pushState
用於向瀏覽器的歷史記錄堆疊添加新條目。使用者可以導航回先前的狀態。例如,用於對產品列表進行排序:
window.history.replaceState
用於替換瀏覽器歷史記錄堆疊中的當前條目。使用者無法導航回先前的狀態。例如,用於切換應用程式的語言環境:
路由與導航的運作原理
應用程式路由器 (App Router) 使用混合方法來處理路由和導航。在伺服器端,您的應用程式代碼會按路由區段自動進行 代碼分割 (code-splitting)。在客戶端,Next.js 會 預取 (prefetch) 並 快取 (cache) 路由區段。這意味著當使用者導航到新路由時,瀏覽器不會重新載入頁面,只有變更的路由區段會重新渲染,從而提升導航體驗和效能。
1. 代碼分割 (Code Splitting)
代碼分割允許您將應用程式代碼拆分為較小的套件,供瀏覽器下載和執行。這減少了每次請求傳輸的數據量和執行時間,從而提高效能。
伺服器元件 允許您的應用程式代碼按路由區段自動進行代碼分割。這意味著導航時只會載入當前路由所需的代碼。
2. 預取 (Prefetching)
預取是一種在使用者訪問路由前,在背景預先載入路由的方式。
Next.js 中有兩種預取路由的方式:
<Link>
元件:當路由出現在使用者的視野中時,會自動進行預取。預取發生在頁面首次載入或通過滾動進入視野時。router.prefetch()
:可以使用useRouter
鉤子以程式方式預取路由。
<Link>
的預設預取行為(即當 prefetch
屬性未指定或設為 null
時)會根據您是否使用 loading.js
而有所不同。只有共享的佈局,直到第一個 loading.js
檔案為止的元件「樹」會被預取並快取 30 秒。這減少了獲取整個動態路由的成本,意味著您可以顯示 即時載入狀態,為使用者提供更好的視覺反饋。
您可以通過將 prefetch
屬性設為 false
來禁用預取。或者,您可以通過將 prefetch
屬性設為 true
來預取超出載入邊界的完整頁面數據。
更多資訊請參閱 <Link>
API 參考文件。
重要須知:
- 預取功能在開發環境中不會啟用,僅在生產環境中有效。
3. 快取 (Caching)
Next.js 有一個稱為 路由器快取 (Router Cache) 的 記憶體客戶端快取。當使用者在應用程式中導航時,預取 的路由區段和已訪問路由的 React 伺服器元件負載 (Payload) 會被儲存在快取中。
這意味著在導航時,會盡可能重用快取,而不是向伺服器發送新請求,從而通過減少請求和傳輸的數據量來提高效能。
了解更多關於 路由器快取 的運作方式和如何配置它。
4. 部分渲染 (Partial Rendering)
部分渲染意味著在導航時,只有變更的路由區段會在客戶端重新渲染,任何共享的區段都會被保留。
例如,在導航兩個兄弟路由 /dashboard/settings
和 /dashboard/analytics
之間時,settings
頁面會被卸載,analytics
頁面會以新狀態掛載,而共享的 dashboard
佈局會被保留。這種行為也存在於同一動態區段的兩個路由之間,例如 /blog/[slug]/page
和從 /blog/first
導航到 /blog/second
。

如果沒有部分渲染,每次導航都會導致整個頁面在客戶端重新渲染。只渲染變更的區段減少了傳輸的數據量和執行時間,從而提高效能。
5. 軟導航 (Soft Navigation)
瀏覽器在頁面之間導航時會執行「硬導航」。Next.js 應用程式路由器實現了頁面之間的「軟導航」,確保只有變更的路由區段會重新渲染(部分渲染)。這使得客戶端 React 狀態在導航期間得以保留。
6. 前進和後退導航
預設情況下,Next.js 會為前進和後退導航保持滾動位置,並重用 路由器快取 中的路由區段。
7. pages/
和 app/
之間的路由
當從 pages/
逐步遷移到 app/
時,Next.js 路由器會自動處理兩者之間的硬導航。為了檢測從 pages/
到 app/
的轉換,有一個客戶端路由器過濾器會利用應用路由的機率性檢查,這偶爾會導致誤判。預設情況下,這種情況應該非常罕見,因為我們將誤判機率配置為 0.01%。這個機率可以通過 next.config.js
中的 experimental.clientRouterFilterAllowedRate
選項進行自訂。需要注意的是,降低誤判率會增加客戶端套件中生成的過濾器的大小。
或者,如果您希望完全禁用此處理並手動管理 pages/
和 app/
之間的路由,可以在 next.config.js
中將 experimental.clientRouterFilter
設為 false。當此功能被禁用時,任何與應用路由重疊的頁面動態路由預設將無法正確導航。