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
您可以在 Page 组件及其子组件中自由使用此类 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年入职