# next实战案例:内容平台架构设计
# 场景定义(接近真实业务)
目标:做一个内容平台,包含首页、文章详情、作者主页、后台发布。
要求:
- SEO 强(搜索引擎可抓取)
- 首页访问量高(缓存命中要高)
- 发布后 1 分钟内用户可见
- 后台交互流畅(富交互编辑器)
# 技术决策
# 路由与目录
app/(site)/page.tsx:首页app/(site)/post/[slug]/page.tsx:详情app/(site)/author/[id]/page.tsx:作者页app/(admin)/editor/page.tsx:后台编辑器app/api/revalidate/route.ts:发布后失效接口
# 组件分层
- Server Components:内容渲染、SEO 元信息、关联数据拼装
- Client Components:编辑器、点赞、评论输入、收藏按钮
# 数据策略设计
# 首页列表(高流量)
revalidate: 60tags: ["post-list"]
# 详情页(中等流量)
revalidate: 300tags: ["post:{id}"]
# 用户态操作(点赞/收藏)
cache: "no-store"- 写操作走 Server Actions/Route Handlers
# 关键代码示例
app/(site)/page.tsx
async function getPostList() {
const res = await fetch("https://api.example.com/posts", {
next: { revalidate: 60, tags: ["post-list"] },
});
return res.json();
}
export default async function HomePage() {
const posts = await getPostList();
return (
<main>
{posts.map((p: any) => (
<article key={p.id}>{p.title}</article>
))}
</main>
);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
发布后触发失效:
import { revalidateTag } from "next/cache";
export async function POST(req: Request) {
const { postId } = await req.json();
revalidateTag("post-list");
revalidateTag(`post:${postId}`);
return Response.json({ ok: true });
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 交互体验优化
# 1)分段渲染
详情页主内容先返回,推荐/评论区放入 Suspense,避免慢接口拖住首屏。
# 2)编辑器隔离
后台编辑器组件使用 Client Components,前台展示仍保持 Server Components 主导。
# 3)乐观更新
点赞使用 useOptimistic,请求失败再回滚,保证交互反馈速度。
# 性能与稳定性观测
关键指标:
- TTFB(首页、详情)
- 缓存命中率(post-list、post:id)
- 首屏 HTML 大小与 hydration 时间
- 发布后缓存失效延迟
监控建议:
- 每个请求打
requestId - 记录 revalidate 触发日志
- 对比冷缓存与热缓存性能
# 常见线上问题与处理
# 问题 1:发布后部分节点不更新
通常是多实例环境中失效事件未正确广播。
解决:统一由后端发布服务调用失效接口,确保幂等与重试。
# 问题 2:详情页偶发慢
通常是慢数据和主渲染路径耦合。
解决:拆 Suspense 边界,保证主内容优先输出。
# 问题 3:客户端包体变大
通常是 "use client" 作用域过大。
解决:将交互组件下沉到最小叶子节点。
# 小结
Next 在生产中的正确姿势不是“默认全 SSR”,而是:
按页面价值拆渲染策略,按业务实时性设计缓存失效,按交互复杂度切 Server/Client 边界。
这套方法能兼顾 SEO、性能和开发效率。