Next.js App Router 数据获取:Server Component、缓存与流式渲染
默认就在服务端
App Router 下,未标记 "use client" 的组件默认是 Server Component。可以直接:
- 读文件系统(如 Markdown 博客)
- 访问数据库(同 VPC 内网)
- 调用内部 API,且不暴露密钥
// app/blog/page.tsx — Server Component
import { getAllPosts } from "@/lib/posts";
export default function BlogPage() {
const posts = getAllPosts(); // 构建时或请求时执行
return (
<ul>
{posts.map((p) => (
<li key={p.slug}>{p.title}</li>
))}
</ul>
);
}
fetch 的四种缓存语义
| 写法 | 行为 |
|---|---|
fetch(url) | 默认缓存(静态生成时复用) |
fetch(url, { cache: "no-store" }) | 每次请求都打源站 |
fetch(url, { next: { revalidate: 60 } }) | ISR:60 秒内用缓存 |
export const dynamic = "force-dynamic" | 整页动态 |
个人博客读本地 Markdown,通常用 构建时静态生成(generateStaticParams),无需 no-store。
静态路径与动态段
export async function generateStaticParams() {
return getAllSlugs().map((slug) => ({ slug }));
}
构建阶段为每篇文章生成 HTML,CDN 友好;新文章发布后需 重新 build 或配合 revalidatePath。
loading.tsx 与 Suspense
// app/blog/loading.tsx
export default function Loading() {
return <p className="animate-pulse">加载中…</p>;
}
路由切换时自动展示,适合慢查询;快路径(本地 fs)可省略。
何时用 Client Component
仅在需要以下能力时加 "use client":
useState/useEffect- 浏览器 API(
localStorage、剪贴板) - 事件监听(主题切换、搜索框防抖)
数据仍应在 Server Component 拉取,通过 props 下发,避免 瀑布请求。
反模式
- 在
useEffect里fetch('/api/posts')渲染列表 — 多一轮 RTT - 全站
"use client"— 失去 RSC 体积与 SEO 优势 - 混用 Pages Router 的
getServerSideProps心智 — 改读 App Router 文档
小结
数据靠近数据源、交互靠近浏览器。ZhuBook 博客列表与文章页均在服务端读 content/posts,评论表单才是 Client Component——这是 App Router 的典型切分。
相关阅读
- React Server Components 入门:心智模型与边界2026-05-12
- TypeScript 2026 实战:从类型体操到可维护工程2026-05-18
- Tailwind CSS 设计令牌:用 CSS 变量构建可主题化的个人站2026-05-11
本站评论 (0)
- 暂无评论,来说第一句吧。