Next.js 是一個流行的 Web 開發框架,它在 13 版中引入了新的 App Router 作為其預設路由系統。
我確信有些人參與的專案同時使用了 Pages Router 和 App Router,並且不知道該如何寫。我就是這樣的!
特別是,Pages Router 和 App Router 在與應用程式開發核心相關的領域存在顯著差異,例如如何根據檔案結構定義路由、如何處理 URL 的動態部分、渲染如何運作以及如何從 API 中擷取資料。
圍繞著「經常混淆」的點,我將簡要列出 Pages Router 和 App Router 之間的主要區別,以作提醒!
檔案路由的差異
Pages Router:將檔案名稱轉換為路徑的簡單方法
放在pages目錄下.js
, .jsx
, .ts
, .tsx
就像檔案名稱成為 URL 路徑一樣簡單。
例子:src/page/about.tsx
⇒ 路由是/about
這將是。
App Router:由資料夾和特定檔案名稱構成
應用程式路由器src/app
您可以透過在其下方放置資料夾和檔案來進行路由。
但是,如果在用於路由的檔案名稱中新增名為「page」的特定檔案名,它將被視為與該路徑對應的頁面的內容。
例子:src/app/about/page.tsx
⇒ 路由是/about
這將是。
表徵 App Router 的特殊文件
除了page.tsx之外,App Router中還有其他有意義的檔案。
app/
├── page.tsx --> 頁面內容。這是您最常使用的文件。
├── route.tsx --> API 定義(不能與 page.js 共存)。
├── layout.tsx --> 常用外觀。
├── loading.tsx --> 載入介面。
├── error.tsx --> 錯誤介面。
├── global-error.tsx --> 全域錯誤介面。
├── template.tsx --> 常用外觀(重設佈局)。
├── default.tsx --> 預設介面。
└── not-found.tsx --> 拋出 notFound 函數時所顯示的介面。
我個人最驚訝的是 not-found.tsx。只要準備這個頁面,當你造訪一個不存在的 URL 時,它就會自動顯示出來。它的實現如此簡單,讓我印象深刻。
渲染差異
Pages Router 中的元件基本上都是設計在客戶端互動的,伺服器端的渲染主要是為了加快初始顯示速度和SEO目的。useState
或者useEffect
您可以在頁面元件及其子元件中自由使用此類 React Hooks。
另一方面,App Routerapp/
組件除非明確指定,否則它將預設被視為伺服器元件。。所以useState
或者useEffect
例如React Hooks 不可用客戶端操作,例如 onClick事件處理程序也不可用。
因此,要使用 App Router 建立 CSR,use client
寫:
use client
伺服器元件和客戶端元件宣告邊界是。use client
如果您聲明它,不僅該元件而且其所有導入都將被視為客戶端元件。
動態路由[○○]
Next.js 提供了一種處理「動態 URL」的機制,其中 URL 的一部分會根據使用者或內容而變化,例如部落格或新聞文章詳細資訊頁面。動態路由是。
例如,假設有一個連結可以將您帶到文章 A 和文章 B。

import Link from "next/link";
const linkStyle=`ext-lg font-bold border-b border-primary px-1`
export default function page() {
return (
<div>
<div className="flex gap-6">
<Link href="/post/A" className={linkStyle}>記事Aへのリンク</Link>
<Link href="/post/B" className={linkStyle}>記事Bへのリンク</Link>
</div>
</div>
);
}
連結目的地


如果您想要動態路由,[slug]
如果你建立一個名為post/A
但post/B
但您可以使用相同的模板。
*[ ] 中的命名是可選的。slug
不一定要這樣
應用程式路由器
/app/post/[slug]/page.tsx
export default aysinc function PostPage({ params }: { params: Promise<{ slug: string }>) {
const {slug}= await params;
return (
<div>
<h1>記事: {slug}</h1>
</div>
);
}
params
我們使用。params.slug
到 URL[slug]
該部分將被包括在內。
※ params
之前參數取得不需要異步,但從 Next.js 15 開始,改為異步。props
看來你需要將其定義為 Promise 類型。
對於頁面路由器
/pages/post/[slug].tsx
import { useRouter } from 'next/router';
export default function PostPage() {
const router = useRouter();
const { slug } = router.query;
return (
<div>
<h1>記事: {slug}</h1>
</div>
);
}
useRouter
我們使用。router.query.slug
到 URL[slug]
該部分的值將被輸入。
如何取得 API 數據
microCMS 是 Liberogic 專欄中重點介紹的,它與 Next.js 等框架配合良好。
應用程式路由器
保持簡單fetch
或者aysnc
await
您可以使用
然而,use client
聲明此內容的文件將成為 CSR。aysnc
await
將不再可用!
async function getPost() {
const res = await fetch(`https://.../api/data/`);
// エラーハンドリング例
if (!res.ok) {
throw new Error(`Failed to fetch post: ${res.status}`);
}
return res.json();
}
被叫方
export default function Example() {
const data = await getPost()
// ... data を使って表示 ...
}
對於頁面路由器
getStaticProps
使用獲得的數據props
到頁面元件。
export async function getServerSideProps(context) {
// context.req, context.res などにアクセス可能
const res = await fetch(`https://.../api/data/`, {
headers: { Cookie: context.req.headers.cookie } // 例: Cookieを渡す
});
const data = await res.json();
return {
props: {
data,
},
};
}
被叫方
export default function Example({ data }) {
// ... data を使って表示 ...
}
了解兩種路由器,掌握 Next.js!
就我而言,我使用 Next.js 的第一個專案是 App Router。
後來,當我從事另一個專案並使用 Pages Router 時,我發現自己很疑惑,“創建新頁面時,文件名應該是 index.tsx 還是 page.tsx?”
本文僅涵蓋了 Next.js 的一小部分,但透過研究 App Router 和 Pages Router 之間的區別,我能夠在腦海中對它有一個更清晰的認識。
就我個人而言,我喜歡編寫 App Router 的簡單性,但我也希望能夠處理 Pages Router 專案。
理想的情況是深入了解 Next.js,並能夠根據專案或工作使用不同的路由器!
我使用 JavaScript、React 和 Next.js 開發前端項目,專注於標記語言。當我參與開發的網站成功發佈時,我感到無比欣慰!我的嗜好是彈吉他。我既喜歡寫程式碼,也喜歡玩程式碼!
Hiratchi
前端工程師 / 2022年入職