为什么选择 App Router?
Next.js 13 引入了全新的 App Router,到了 14 版本已经非常稳定。相比传统的 Pages Router,App Router 带来了:
- React Server Components (RSC) — 默认在服务端渲染,零客户端 JS
- 嵌套布局 — 共享 UI 变得极其简单
- 流式渲染 — 渐进式页面加载
- 更强的类型安全 — 参数、搜索参数都有完整类型推断
项目结构
一个典型的 App Router 项目结构如下:
app/
├── layout.tsx # 根布局
├── page.tsx # 首页
├── posts/
│ ├── layout.tsx # 文章页共享布局
│ └── [slug]/
│ └── page.tsx # 文章详情
└── api/
└── posts/
└── route.ts # API 路由
核心概念
1. Server Components(默认)
在 App Router 中,所有组件默认都是 服务端组件。这意味着:
// 这是一个服务端组件 — 可以直接访问文件系统、数据库
import fs from "fs";
export default async function PostList() {
const posts = await getPosts(); // 直接 await,不需要 useEffect
return (
<ul>
{posts.map((post) => (
<li key={post.slug}>{post.title}</li>
))}
</ul>
);
}
2. Client Components
当需要交互时,加上 "use client" 指令:
"use client";
import { useState } from "react";
export function ThemeToggle() {
const [dark, setDark] = useState(false);
return <button onClick={() => setDark(!dark)}>切换主题</button>;
}
3. 静态生成
对于博客类的站点,静态导出是最佳选择:
// next.config.ts
const config: NextConfig = {
output: "export",
};
配合 generateStaticParams:
export function generateStaticParams() {
const posts = getAllPosts();
return posts.map((post) => ({ slug: post.slug }));
}
数据获取模式
| 场景 | 方法 | 适用 |
|---|---|---|
| 静态内容 | generateStaticParams + 直接读取 | 博客、文档 |
| 动态内容 | Server Component + fetch | 实时数据 |
| 客户端数据 | useEffect + fetch | 用户特定数据 |
性能优化建议
- 减少 Client Components — 尽可能让组件保持在服务端
- 使用
next/image— 自动优化图片 - 字体优化 — 使用
next/font避免布局偏移 - 流式渲染 — 用
loading.tsx和Suspense提升感知性能
总结
App Router 代表了 React 全栈框架的未来方向。它让你能在一个项目里灵活混合服务端和客户端渲染,写出更简洁、更高性能的应用。
对于个人博客这种内容型站点,静态导出 + Markdown 的组合几乎是最优解 — 这也是本站采用的技术方案。