1.1 什么是 Next.js
Next.js 是由 Vercel 开发并维护的 React 全栈框架。它在 React 的基础上提供了路由、服务端渲染、数据获取、图片优化等生产级特性,使开发者无需从零配置就能构建高性能的 Web 应用。自 2016 年发布以来,Next.js 已成为全球最受欢迎的 React 框架之一。
2023 年随着 Next.js 13 引入 App Router,2024 年 Next.js 15 进一步稳定了这一架构。App Router 基于 React Server Components(RSC)规范,从根本上改变了 React 应用的渲染模型,将"服务器优先"的思路贯穿整个框架设计。
Next.js 15 新特性React 19 稳定支持、Turbopack 构建工具正式 GA、改进的缓存语义(fetch 默认不再缓存)、`after()` API 支持响应后执行副作用。本教程全程使用 Next.js 15 + React 19。
Next.js 解决了哪些问题
纯 React 应用(Create React App)是客户端渲染(CSR):浏览器下载空 HTML → 下载 JS Bundle → 执行 JS → 渲染页面。这带来三个问题:
- 首屏慢:用户需要等待 JS 下载和执行才能看到内容
- SEO 差:爬虫拿到空 HTML,无法索引页面内容
- 配置繁琐:路由、代码分割、SSR 等需要手动配置
Next.js 通过服务端渲染(SSR)、静态生成(SSG)和 React Server Components 三种策略,从架构层面解决了这些问题。
1.2 创建第一个 Next.js 项目
Next.js 官方提供了 create-next-app 脚手架,可以快速创建包含 TypeScript、ESLint、Tailwind CSS 的完整项目模板。
# 使用 pnpm 创建项目(推荐)
pnpm create next-app@latest my-app
# 交互式提示选项:
# ✔ Would you like to use TypeScript? › Yes
# ✔ Would you like to use ESLint? › Yes
# ✔ Would you like to use Tailwind CSS? › Yes
# ✔ Would you like your code inside a `src/` directory? › No
# ✔ Would you like to use App Router? › Yes
# ✔ Would you like to use Turbopack for `next dev`? › Yes
# ✔ Would you like to customize the import alias? › No
SHELL
# 启动开发服务器
cd my-app
pnpm dev
# 访问 http://localhost:3000
SHELL
生成的项目结构
my-app/
├── app/ # App Router 根目录
│ ├── layout.tsx # 根布局(必须存在)
│ ├── page.tsx # 根页面 /
│ ├── globals.css # 全局样式
│ └── favicon.ico
├── public/ # 静态资源
├── next.config.ts # Next.js 配置
├── tsconfig.json
└── package.json
STRUCTURE
1.3 App Router 核心约定文件
App Router 使用一套特殊的文件命名约定来定义路由行为。每个文件名都有其专属语义,Next.js 会根据文件名自动决定如何处理请求。这是"约定优于配置"原则的典型体现。
- page.tsx 定义路由的 UI,使该路由可公开访问。一个目录只能有一个 page.tsx,它对应该目录的 URL 路径。
- layout.tsx 定义该路由及其所有子路由共享的 UI 布局。布局在导航时不会重新渲染,状态得以保留。根布局(app/layout.tsx)必须包含 <html> 和 <body> 标签。
- loading.tsx 定义加载 UI,基于 React Suspense 实现。当页面数据正在加载时,Next.js 自动显示此组件,无需手动编写 Suspense 边界。
- error.tsx 定义错误 UI,必须是 Client Component('use client')。当路由或其子路由抛出错误时,Next.js 会显示此组件,相当于 React Error Boundary。
-
not-found.tsx
当调用
notFound()函数或路由不存在时显示的 404 UI。 - route.ts 定义 API 端点(Route Handler),处理 HTTP 请求,不能与 page.tsx 在同一目录下共存。
- middleware.ts 在请求完成之前运行的代码,位于项目根目录(与 app/ 同级)。常用于认证检查、重定向、请求头修改。
- template.tsx 类似 layout,但每次导航都会创建新实例,状态不保留。适合需要重置状态或重新执行进场动画的场景。
1.4 App Router vs Pages Router 的本质区别
Next.js 同时支持 App Router(app/ 目录)和 Pages Router(pages/ 目录),两者可以在同一项目中共存,但新项目应优先使用 App Router。理解两者的本质区别有助于迁移老项目和做技术选型。
Pages Router(旧)
- 所有组件默认是客户端组件
- 通过 getStaticProps / getServerSideProps 获取数据
- _app.tsx 全局布局,每次导航重渲染
- 不支持嵌套布局
- 路由文件即页面文件
- API 放在 pages/api/ 目录
- React 18 功能受限
App Router(新)
- 所有组件默认是服务端组件
- 直接在组件中使用 async/await 获取数据
- layout.tsx 嵌套布局,导航时不重渲染
- 支持深层嵌套布局
- page.tsx / layout.tsx 分离关注点
- API 使用 route.ts 定义
- 全面支持 React 19 新特性
迁移注意Pages Router 中的 getServerSideProps 和 getStaticProps 在 App Router 中已不再使用。数据获取改为直接在 Server Component 中调用 async/await,或使用新的缓存 API。
渲染模型对比
| 特性 | Pages Router | App Router |
|---|---|---|
| 默认渲染位置 | 客户端 | 服务端 |
| 数据获取方式 | 特殊 API 函数 | async/await 直接调用 |
| 布局复用 | 需要手动封装 | layout.tsx 自动嵌套 |
| 流式渲染 | 不支持 | Suspense + streaming |
| Server Actions | 不支持 | 原生支持 |
| React 版本 | React 18 | React 19 |
1.5 根布局与页面组件
App Router 要求 app/layout.tsx 必须存在,这是整个应用的根布局。它包裹所有页面,提供全局 HTML 结构、字体加载、全局 Provider 等。由于根布局输出 <html> 和 <body> 标签,请勿在页面组件中重复添加这些标签。
// app/layout.tsx — 根布局(Server Component)
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import './globals.css'
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: 'My App',
description: 'Generated by Next.js',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="zh-CN">
<body className={inter.className}>
{children}
</body>
</html>
)
}
TSX
// app/page.tsx — 根页面(/ 路由)
// 默认为 Server Component,可以直接使用 async/await
export default async function HomePage() {
// 服务端直接获取数据,无需 useEffect
const posts = await fetchPosts()
return (
<main>
<h1>欢迎使用 Next.js 15</h1>
{posts.map(post => (
<article key={post.id}>{post.title}</article>
))}
</main>
)
}
TSX
Server Component 默认行为在 App Router 中,所有 .tsx / .ts 文件默认都是 Server Component。只有在文件顶部添加 'use client' 指令,才会变成 Client Component。这是与 Pages Router 最重要的心智模型转变。
1.6 next.config.ts 配置文件
Next.js 15 将配置文件从 JavaScript 升级为 TypeScript(next.config.ts),提供完整的类型提示。配置文件用于自定义 Next.js 的构建、运行时行为,包括环境变量、图片域名白名单、重写规则、实验性功能开关等。
// next.config.ts
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
// 图片域名白名单(next/image 远程图片需要)
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'images.unsplash.com',
},
],
},
// 实验性功能
experimental: {
// PPR: Partial Prerendering(静态 shell + 动态数据流)
ppr: true,
},
// 重写规则(将旧路由映射到新路由)
async rewrites() {
return [
{ source: '/old-blog/:slug', destination: '/blog/:slug' },
]
},
}
export default nextConfig
TS