Next.js 16深度解析:React Server Components与全栈新范式

Next.js 16代表了React全栈框架的重大进化。React Server Components (RSC) 从实验走向成熟,Server Actions成为标准。本文将深入这些变革。

React Server Components 核心概念

RSC让组件在服务端运行,零客户端JavaScript:

tsx
// app/posts/page.tsx — 这是一个Server Component(默认)
import { db } from '@/lib/db';

export default async function PostsPage() {
  const posts = await db.post.findMany({
    orderBy: { createdAt: 'desc' },
    take: 10,
  });

  return (
    <main>
      <h1>最新文章</h1>
      {posts.map((post) => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          <PostActions postId={post.id} /> {/* Client Component */}
        </article>
      ))}
    </main>
  );
}
tsx
// PostActions.tsx — Client Component
'use client';

import { likePost } from '@/actions/post';
import { useState } from 'react';

export function PostActions({ postId }: { postId: string }) {
  const [liked, setLiked] = useState(false);

  return (
    <button onClick={async () => {
      await likePost(postId);
      setLiked(true);
    }}>
      {liked ? '❤️' : '🤍'}
    </button>
  );
}

Server Actions

Server Actions让服务端逻辑调用像函数调用一样简单:

tsx
// app/actions/post.ts
'use server';

import { revalidatePath } from 'next/cache';
import { auth } from '@/lib/auth';
import { db } from '@/lib/db';

export async function createPost(formData: FormData) {
  const session = await auth();
  if (!session?.user) throw new Error('Unauthorized');

  const title = formData.get('title') as string;
  const content = formData.get('content') as string;

  await db.post.create({
    data: { title, content, authorId: session.user.id },
  });

  revalidatePath('/posts');
}

Partial Prerendering(PPR)

PPR允许在同一页面混合静态和动态内容:

tsx
// 静态壳立即展示,动态内容流式插入
import { Suspense } from 'react';

export default function Page() {
  return (
    <div>
      <StaticNav />        {/* 静态预渲染 */}
      <StaticHero />       {/* 静态预渲染 */}
      <Suspense fallback={<Skeleton />}>
        <DynamicRecommendations />  {/* 动态渲染 */}
      </Suspense>
    </div>
  );
}

数据获取模式

并行数据获取

tsx
export default async function Dashboard() {
  // 并行请求,无瀑布
  const [user, posts, analytics] = await Promise.all([
    getUser(),
    getPosts(),
    getAnalytics(),
  ]);

  return <DashboardUI user={user} posts={posts} analytics={analytics} />;
}

流式渲染

tsx
import { Suspense } from 'react';

export default function Page() {
  return (
    <main>
      <h1>Dashboard</h1>
      <Suspense fallback={<p>Loading feed...</p>}>
        <SlowFeed />
      </Suspense>
      <Suspense fallback={<p>Loading stats...</p>}>
        <SlowStats />
      </Suspense>
    </main>
  );
}

路由与中间件

typescript
// middleware.ts — 灵活的路由守卫
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  const token = request.cookies.get('token');

  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: ['/dashboard/:path*', '/admin/:path*'],
};

总结

Next.js 16推动的RSC+Server Actions架构代表了Web开发的范式转移。它让我们重新思考客户端与服务端的边界,用更少的JavaScript交付更好的用户体验。

关键变化:

  1. Server First — 默认服务端渲染,客户端按需添加
  2. 零Bundle组件 — Server Component不增加JS体积
  3. 数据获取简化 — 无需API路由,直接await数据库
  4. 渐进式增强 — PPR让静态页面也拥有动态能力