# 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: 60
  • tags: ["post-list"]

# 详情页(中等流量)

  • revalidate: 300
  • tags: ["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

发布后触发失效:

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

# 交互体验优化

# 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、性能和开发效率。