渲染模式

Next.js 支持多种渲染策略,可以针对不同页面选择最合适的方式。

Server Components(服务端组件)

App Router 中的组件默认为 Server Components:

// 这是一个 Server Component(默认)
async function PostList() {
  const posts = await fetch('https://api.example.com/posts')
  const data = await posts.json()

  return (
    <ul>
      {data.map(post => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}

优势:

  • 直接在服务端获取数据,减少客户端 JavaScript
  • 可以直接访问数据库、文件系统等后端资源
  • 敏感信息(API 密钥等)不会泄露到客户端

Client Components(客户端组件)

需要交互或浏览器 API 时使用 'use client' 指令:

'use client'

import { useState } from 'react'

export default function Counter() {
  const [count, setCount] = useState(0)

  return (
    <button onClick={() => setCount(count + 1)}>
      计数:{count}
    </button>
  )
}

Static Generation(静态生成)

在构建时生成 HTML:

// 构建时生成所有文章路径
export async function generateStaticParams() {
  const posts = await fetch('https://api.example.com/posts').then(r => r.json())

  return posts.map(post => ({
    slug: post.slug,
  }))
}

ISR(增量静态再生)

结合静态生成和服务端渲染的优势:

async function Page() {
  const data = await fetch('https://api.example.com/data', {
    next: { revalidate: 60 } // 每 60 秒重新验证
  })

  return <div>{/* ... */}</div>
}

渲染模式选择指南

场景 推荐模式
静态内容(博客、文档) SSG
动态内容 + SEO SSR
不常变化的动态内容 ISR
纯交互页面(Dashboard) CSR

渲染模式

Next.js 可依頁面選擇 SSR、SSG、ISR 或以客戶端為主。

Server Components(伺服器元件)

預設在伺服器執行,可 fetch、存取後端資源,並減少送到瀏覽器的 JS。

async function PostList() {
  const data = await fetch('https://api.example.com/posts').then(r => r.json())
  return (
    <ul>{data.map((p: { id: string; title: string }) => <li key={p.id}>{p.title}</li>)}</ul>
  )
}

Client Components(客戶端元件)

需要 useState、事件或瀏覽器 API 時,檔案頂端加 'use client'

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

export default function Counter() {
  const [count, setCount] = useState(0)
  return (
    <button type="button" onClick={() => setCount(count + 1)}>
      計數:{count}
    </button>
  )
}

Static Generation(靜態產生)

建置時產生路徑與 HTML,例如動態路由搭配 generateStaticParams

export async function generateStaticParams() {
  const posts = await fetch('https://api.example.com/posts').then(r => r.json())
  return posts.map((post: { slug: string }) => ({ slug: post.slug }))
}

ISR(增量靜態再生)

fetchnext.revalidate 指定間隔(秒),過期後背景再驗證:

async function Page() {
  const res = await fetch('https://api.example.com/data', {
    next: { revalidate: 60 },
  })
  const data = await res.json()
  return <div>{/* 使用 data */}</div>
}

選擇指引

情境 建議
部落格、文件等靜態內容 SSG
動態內容且需 SEO SSR
變動不頻繁的列表/內容頁 ISR
後台、大量互動 以 Client Component(CSR)為主

Rendering Modes

Next.js lets you mix server and client rendering in one app. Choosing the right mode balances interactivity, SEO, freshness, and infrastructure cost.

Server Components (default)

In the App Router, components in app/ are Server Components unless marked otherwise. They run on the server, can access databases and secrets directly, and send minimal JavaScript to the client.

// app/items/page.tsx — Server Component
import { db } from "@/lib/db";

export default async function ItemsPage() {
  const items = await db.item.findMany();
  return (
    <ul>
      {items.map((i) => (
        <li key={i.id}>{i.name}</li>
      ))}
    </ul>
  );
}

No useState or browser-only APIs here—split interactive pieces into Client Components.

Client Components

Add "use client" at the top of files that need hooks, event handlers, or browser APIs:

"use client";

import { useState } from "react";

export function Counter() {
  const [n, setN] = useState(0);
  return <button onClick={() => setN(n + 1)}>{n}</button>;
}

Compose small client islands inside larger server trees to keep bundles lean.

Static generation and ISR

Static pages are built at build time (output: "export" or default static segments). ISR (Incremental Static Regeneration) rebuilds pages in the background after a time window:

export const revalidate = 3600; // seconds

export default async function Page() {
  const data = await fetch("https://api.example.com/stats", {
    next: { revalidate: 3600 },
  }).then((r) => r.json());
  return <pre>{JSON.stringify(data)}</pre>;
}

Use static/ISR for content that changes occasionally; use dynamic rendering (no cache, or force-dynamic) for per-request personalization.

Choosing a mode

Need Prefer
SEO, fast TTFB, no client JS for content Server Components + static or ISR
Forms, animations, charts Client Components (or mix)
Real-time or user-specific data every request Dynamic server rendering
CDN-cached marketing pages Static or ISR with revalidate

Start with Server Components and static/ISR; add Client Components and dynamic rendering only where the UX requires it.