Q3: 解释 Next.js 15 中的渲染模式:SSR、SSG、CSR 以及 ISR(增量静态再生)。它们分别在什么场景下使用?

94 阅读3分钟

Next.js 面试题详细答案 - Q3

Q3: 解释 Next.js 15 中的渲染模式:SSR、SSG、CSR 以及 ISR(增量静态再生)。它们分别在什么场景下使用?

渲染模式概览

Next.js 15 支持四种主要的渲染模式,每种都有其特定的使用场景和优势。

1. SSR (Server-Side Rendering) - 服务端渲染

工作原理:每次请求时在服务器上渲染页面,然后发送完整的 HTML 到客户端。

// 默认行为 - 每次请求时渲染
async function BlogPost({ params }) {
  const post = await fetch(`/api/posts/${params.slug}`, {
    cache: 'no-store', // 禁用缓存
  })

  return (
    <article>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
      <time>{new Date().toLocaleString()}</time>
    </article>
  )
}

使用场景

  • 个性化内容(用户仪表盘)
  • 实时数据(股票价格、新闻)
  • 需要认证的页面
  • 频繁更新的内容

优势

  • 实时数据
  • SEO 友好
  • 个性化内容

劣势

  • 服务器负载高
  • 响应时间较长

2. SSG (Static Site Generation) - 静态站点生成

工作原理:构建时预渲染页面,生成静态 HTML 文件。

// 静态生成
async function BlogList() {
  const posts = await fetch('/api/posts', {
    cache: 'force-cache', // 强制缓存
  })

  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>
          <Link href={`/blog/${post.slug}`}>{post.title}</Link>
        </li>
      ))}
    </ul>
  )
}

// 动态路由的静态生成
export async function generateStaticParams() {
  const posts = await fetch('/api/posts')
  return posts.map((post) => ({
    slug: post.slug,
  }))
}

使用场景

  • 博客文章
  • 产品页面
  • 文档网站
  • 营销页面

优势

  • 极快的加载速度
  • 低服务器成本
  • 高可用性
  • 优秀的 SEO

劣势

  • 构建时间长
  • 内容更新需要重新构建

3. CSR (Client-Side Rendering) - 客户端渲染

工作原理:在客户端使用 JavaScript 渲染页面。

'use client'
import { useState, useEffect } from 'react'

function Dashboard() {
  const [data, setData] = useState(null)
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    fetch('/api/user-data')
      .then((res) => res.json())
      .then((data) => {
        setData(data)
        setLoading(false)
      })
  }, [])

  if (loading) return <div>加载中...</div>

  return (
    <div>
      <h1>用户仪表盘</h1>
      <p>欢迎, {data.name}!</p>
    </div>
  )
}

使用场景

  • 交互式应用
  • 用户仪表盘
  • 实时聊天
  • 游戏应用

优势

  • 丰富的交互性
  • 快速导航
  • 离线功能

劣势

  • 首屏加载慢
  • SEO 不友好
  • 需要 JavaScript

4. ISR (Incremental Static Regeneration) - 增量静态再生

工作原理:结合 SSG 和 SSR 的优势,在后台更新静态页面。

// 基础 ISR
async function ProductPage({ params }) {
  const product = await fetch(`/api/products/${params.id}`, {
    next: { revalidate: 3600 }, // 1小时后重新验证
  })

  return (
    <div>
      <h1>{product.name}</h1>
      <p>价格: ${product.price}</p>
    </div>
  )
}

// 按需重新验证
export async function GET(request) {
  const { searchParams } = new URL(request.url)
  const secret = searchParams.get('secret')

  if (secret !== process.env.REVALIDATE_SECRET) {
    return Response.json({ message: 'Invalid secret' }, { status: 401 })
  }

  try {
    await revalidatePath('/products')
    return Response.json({ revalidated: true })
  } catch (err) {
    return Response.json({ message: 'Error revalidating' }, { status: 500 })
  }
}

使用场景

  • 电商产品页面
  • 新闻文章
  • 用户生成内容
  • 定期更新的内容

优势

  • 静态页面的性能
  • 动态内容的灵活性
  • 自动更新机制

劣势

  • 首次访问可能较慢
  • 缓存失效延迟

渲染模式选择指南

1. 内容类型决定渲染模式
// 静态内容 - SSG
export default function AboutPage() {
  return <h1>关于我们</h1>
}

// 动态内容 - SSR
async function UserProfile({ params }) {
  const user = await fetch(`/api/users/${params.id}`, {
    cache: 'no-store',
  })
  return <div>{user.name}</div>
}

// 混合内容 - ISR
async function BlogPost({ params }) {
  const post = await fetch(`/api/posts/${params.slug}`, {
    next: { revalidate: 86400 }, // 24小时
  })
  return <article>{post.content}</article>
}
2. 性能考虑
// 性能优化策略
const fetchConfig = {
  // 静态内容 - 永久缓存
  static: { cache: 'force-cache' },

  // 动态内容 - 不缓存
  dynamic: { cache: 'no-store' },

  // 定期更新 - ISR
  isr: { next: { revalidate: 3600 } },

  // 按需更新 - 标签缓存
  tagged: { next: { tags: ['posts'] } },
}
3. 实际应用示例
// 电商网站渲染策略
app / page.js // 首页 - SSG
products /
  page.js[id] / // 产品列表 - ISR (1小时)
  page.js // 产品详情 - ISR (30分钟)
cart / page.js // 购物车 - CSR
dashboard / page.js // 用户仪表盘 - SSR

最佳实践

  1. 默认使用 SSG:适合大多数内容
  2. 个性化内容用 SSR:用户相关数据
  3. 交互式功能用 CSR:复杂用户界面
  4. 定期更新用 ISR:平衡性能和新鲜度

总结

选择合适的渲染模式需要考虑:

  • 内容更新频率
  • 个性化需求
  • 性能要求
  • SEO 重要性
  • 用户体验

Next.js 15 的灵活性允许在同一个应用中混合使用不同的渲染模式,为每种内容选择最合适的策略。