Topics

Next.js Pages Router 与 App Router——理清容易混淆的区别

  • column

作为得到许多支持的网络开发框架,Next.js 在第 13 版本中引入了新的 App Router 作为默认的路由系统。

在同时参与 Pages Router 和 App Router 两种项目的过程中,很容易出现"到底该用哪种写法?"的困惑。我就是这样!!

特别是,从基于文件结构的路由定义方法开始,到URL动态部分的处理方式,再到渲染机制,以及从API获取数据等方面,Pages Router和App Router在应用程序开发的核心部分存在不容忽视的差异。

我们将重点关注「容易混淆的」要点,简要记录 Pages Router 和 App Router 的主要差异作为参考!

文件路由的差异

Pages Router:文件名直接对应路径的简洁性

放置在 pages 目录下的 .js.jsx.ts.tsx 文件,它们的文件名会直接成为 URL 路径,这就是其简洁之处。

例:src/page/about.tsx ⇒ 路由为 /about

App Router:通过文件夹和特定文件名进行结构化

App Router 可以通过在src/app目录下放置文件夹和文件来实现路由。

但是,用于路由的文件名中,名为 page 的特定文件名会被视为对应该路径的页面内容。

例:src/app/about/page.tsx ⇒ 路由将为 /about

App Router 的"特殊文件"特性

在 App Router 中,除了 page.tsx 之外,还有其他具有特定含义的文件。

app/
├── page.tsx           --> ページの中身。これが一番よく使うファイル
├── route.tsx          --> APIの定義(page.jsと共存不可)
├── layout.tsx         --> 共通の見た目
├── loading.tsx        --> 読み込み中の画面
├── error.tsx          --> エラー時の画面
├── global-error.tsx   --> グローバルエラー画面
├── templete.tsx       --> 共通の見た目(リセットされるレイアウト)
├── default.tsx        --> デフォルトの画面
└── not-found.tsx      --> notFound関数がスローされたときの画面

个人来讲,令我惊讶的是 not-found.tsx。只要准备好这个页面,在访问不存在的 URL 时就会自动显示。我对能这么简单地实现它感到惊叹。

渲染的区别

Pages Router 中的组件基本上都是在客户端进行交互的,服务器端渲染主要是为了提高初始显示速度和 SEO。useStateuseEffect 等 React 钩子可以在页面组件及其子组件内自由使用。

另一方面,App Router 中的app/内的组件默认情况下被视为服务器组件,除非明确指定。因此,useStateuseEffect React 钩子无法使用。客户端操作(如 onClick 等)事件处理程序也无法使用

因此,在 App Router 中启用 CSR 需要编写use client

use client

这是 Server Component 和 Client Component 之间的边界声明。声明了use client后,不仅该组件本身,所有导入的组件也都被视为 Client Component。

动态路由 [○○]

Next.js 的动态路由是一种机制,用于处理「动态 URL」——像博客或新闻文章详情页那样,URL 的一部分会根据用户或内容而变化。

例如,假设有链接导航到文章 A 和文章 B。

例如,文章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>
  );
}

每个链接的导航目标

post/A 页面的屏幕截图
post/B 页面的截图

要使用动态路由,创建[slug]文件后,post/Apost/B都可以使用同一个模板。
※方括号内的命名可以任意设置,slug可以用其他名称代替。

App Router 的情况下

/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>
  );
}

使用paramsparams.slug 中包含 URL 中的[slug]部分。

* 注意:以前 params 中的参数获取不需要异步,但从 Next.js 15 开始已改为异步执行。因此,需要将 props 定义为 Promise 类型。

Pages Router 的情况下

/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。URL 中 [slug] 部分的值会存储在 router.query.slug 中。

API 数据获取方法

在本 Liberogic 专栏中也发挥了重要作用的 microCMS 与 Next.js 等框架兼容性良好。

App Router 的情况下

可以直接使用 fetchasync await

但是,声明了 use client 的文件会变成 CSR,所以无法使用 async 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 を使って表示 ...
}

Pages Router 的情况下

使用 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进行前端开发的工作。当我参与的网站顺利发布时,我会感到很高兴!我的爱好是弹吉他。喜欢猫和烤红薯🐱🍠

Hiratch

前端工程师 / 2022年入职

查看本员工的文章

安心的团队体制和迅速的反应能力是我们的优势

Liberogic 拥有经验丰富的员工团队,积极推进项目,因此获得了客户的高度评价。
我们会妥善分配项目经理和总监,确保整个项目顺利进行。 通过避免不必要的全职投入导致的成本增加,并采用适当配置人力资源的方式,从把握业务内容到估价的制作和提交速度都赢得了良好的口碑。

* 本公司不积极开展SES驻场工作等业务,敬请谅解。

Slack、Teams、Redmine、Backlog、Asana、Jira、Notion、Google Workspace、Zoom、Webex 等,您可以使用几乎所有主要的项目管理工具和沟通协作工具。

在使用 SES 或离岸外包的大规模项目中,您是否在技术挑战或解决方案方面需要帮助?

案例分析