Closed godmmt closed 2 weeks ago
在 Next.js 中,App Router 和 Pages Router 是兩種不同的路由機制,用來管理應用程式的導航和渲染。它們各自針對不同的使用情境提供獨特的功能。以下是兩者的詳細比較:
概述:
Pages Router 是 Next.js 的傳統路由機制,從早期版本開始就存在於框架中。它採用基於檔案的路由系統,其中pages
目錄中的每個檔案自動成為應用程式中的路徑。
主要特點:
基於檔案的路由:
pages
目錄中的每個檔案對應一個路徑。例如,pages/index.js
對應到首頁路徑(/
),而pages/about.js
對應到/about
路徑。動態路由:
pages/post/[id].js
可以匹配到像/post/1
、/post/2
等路徑,參數可以透過元件中的query.id
訪問。靜態生成(SSG)和伺服器端渲染(SSR):
getStaticProps
、getStaticPaths
和getServerSideProps
來在構建時間或請求時間獲取資料。API 路由:
pages/api
目錄中創建 API 路由。此目錄中的每個檔案對應一個 API 端點。內建的客戶端導航:
next/link
元件進行客戶端導航,提供預取和更快的頁面過渡效果。範例結構:
/pages
- index.js // 對應到 "/"
- about.js // 對應到 "/about"
- post
- [id].js // 對應到 "/post/:id"
- api
- hello.js // 對應到 "/api/hello"
概述: App Router 是一種較新的路由機制,旨在提供更多靈活性和功能,適用於複雜的應用程式。它允許更模塊化和基於元件的路由和狀態管理。
主要特點:
自定義路由設置:
嵌套路由和版面設計:
資料獲取:
狀態管理:
中介軟體和守衛:
伺服器端功能:
範例設置:
// app/routes.js
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import Post from "./pages/Post";
const router = createBrowserRouter([
{
path: "/",
element: <Home />,
},
{
path: "about",
element: <About />,
},
{
path: "post/:id",
element: <Post />,
},
]);
function App() {
return <RouterProvider router={router} />;
}
export default App;
功能 | Pages Router | App Router |
---|---|---|
路由系統 | 基於檔案 | 程式化 |
動態路由 | 檔案名稱中的方括號 | 路由設置中定義 |
資料獲取 | 靜態生成(SSG)、伺服器端渲染(SSR) | Suspense、並發渲染 |
API 路由 | pages/api 目錄 |
自定義的 API 路由 |
嵌套路由 | 有限 | 完全支援 |
版面管理 | 手動 | 嵌套版面元件 |
狀態管理整合 | 有限 | 高級(Redux、Context API) |
中介軟體和守衛 | 不支援 | 完全支援 |
伺服器端功能 | 基本(SSG、SSR) | 高級(快取、標頭) |
Pages Router 適合較簡單的應用程式或遵循直接、基於檔案的路由結構。快速設置和使用,適合中小型專案。
App Router 更適合複雜的應用程式,需要更先進的路由功能,如嵌套路由、自定義版面和精細的伺服器端行為控制。如果應用程式需要進階的狀態管理和中介軟體功能,也是一個不錯的選擇。
兩種路由器各有其優勢,選擇取決於應用程式的複雜性和具體的需求。
app
目錄:刪除專案根目錄中的 app
目錄,這個目錄是為 App Router 而設置的。
pages
目錄:在專案根目錄中建立一個 pages
目錄。這個目錄是 Pages Router 使用的目錄。
如果有一些頁面文件在 app
目錄中,請將它們移動到 pages
目錄中,並按照 Pages Router 的規則命名和結構(如 index.js
或 [id].js
等)。
像是我們新開的以 App Router 為基礎的專案中,通常會有一個 app
目錄,我們要將目錄中的 page.tsx
和 layout.tsx
文件重新命名和組織,並移動到 pages
目錄。
按照步驟移動:
首頁(Home Page):
將 app/page.tsx
移動到 pages/index.tsx
。
佈局(Layout):
layout.tsx
在 App Router 中是用來包裹所有子路由的。
但在 Pages Router 中,通常是使用 _app.tsx
和 _document.tsx
文件來處理全局佈局和設置。
_app.tsx
:
這個文件用來自定義應用程式的根元件。
將 layout.tsx
的內容移到 _app.tsx
中。
如果沒有 _app.tsx
文件(通常沒有),就在 pages
目錄下建立一個 _app.tsx
文件:
// pages/_app.tsx
import "../styles/globals.css";
import type { AppProps } from "next/app";
function MyApp({ Component, pageProps }: AppProps) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
);
}
export default MyApp;
// You might need to define the Layout component inside the same file or import it from another file
將 layout.tsx
中的佈局內容提取到 Layout
元件中,並在 _app.tsx
文件中使用它。
或者就在 _app.tsx
文件中直接定義佈局元件。
其他頁面:
將 app
目錄下的其他頁面文件按照適當的路由結構移動到 pages
目錄中。
假設有一個 app/about/page.tsx
,就將它移動到 pages/about.tsx
。
next.config.js
:確保 next.config.js
文件中沒有特定於 App Router 的設定,這樣一個基本的 next.config.js
文件應該如下:
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
};
module.exports = nextConfig;
為了確保沒有殘留的設定影響專案,請刪除快取文件和重新安裝相依套件。
運行以下指令:
rm -rf .next node_modules
npm install
確保 package.json
中沒有特定於 App Router 的相依套件。如果有,請移除或替換它們。
import '../styles/globals.css';
import type { AppProps } from 'next/app';
function MyApp({ Component, pageProps }: AppProps) {
return (
<div>
<Component {...pageProps} />
</div>
);
}
export default MyApp;
// pages/_document.tsx
import { Html, Head, Main, NextScript } from 'next/document';
export default function Document() {
return (
<Html lang="en">
<Head></Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
暫時看起來 ok 但不確定
有點不安心
可能還是直接再開一個新專案取代嗎?
took 3 hours
done
但是! 不確定要不要重新開一個新專案
如果要重開,大概需要 3 小時
重開:
這個 issue 綁的 PR #26 被打叉叉是因為 #26 & #30 只會擇一合併進入 main 主分支 最後是 #30 被選擇
所以這個 issue 是已經完成的 ✅
發現專案建置時選錯選項安裝成 App Router 需要改成是 Pages Router
先嘗試手動將目前的專案修改 但如果還是不太確定可不可行就直接砍掉 重新開一個新專案