⚛️ Next.js 服务端组件

React Server Components 源码深度解析

基于 Next.js 15+ 源码深度解读
2026-03-17 | 技术深度解读

📑 目录

第一部分:基础架构

  • RSC 简介
  • 核心架构
  • 渲染流程
  • RSC vs RCC 对比

第二部分:演进历史

  • 架构演进
  • 版本特性

第三部分:核心类解析

  • AppRenderContext
  • LoaderTree / FlightRouterState
  • WorkStore / RequestStore
  • StagedRenderingController

第四部分:核心函数

  • generateDynamicRSCPayload
  • createComponentTree
  • renderToFlightStream

⚛️ React Server Components 简介

React Server Components (RSC) 是 React 的一种新组件类型,在服务器端渲染,零客户端 JavaScript。

核心特性

  • 服务端执行,零客户端 JS
  • 直接访问后端资源
  • 流式渲染支持
  • 与客户端组件无缝集成
  • 自动代码分割

解决的问题

  • 减少客户端包体积
  • 提升首屏加载速度
  • 改善 SEO
  • 简化数据获取
  • 更好的安全性

🏗️ Next.js RSC 核心架构

┌─────────────────────────────────────────────────────┐
│                   Next.js Server                     │
├─────────────────────────────────────────────────────┤
│  ┌──────────────────────────────────────────────┐   │
│  │           app-render.tsx (核心入口)           │   │
│  │  • generateDynamicRSCPayload                  │   │
│  │  • generateDynamicFlightRenderResult          │   │
│  └──────────────────────────────────────────────┘   │
│                       ↓                              │
│  ┌──────────────────────────────────────────────┐   │
│  │         create-component-tree.tsx             │   │
│  │  • 解析 LoaderTree                            │   │
│  │  • 构建 React 组件树                          │   │
│  │  • 处理 parallel routes                       │   │
│  └──────────────────────────────────────────────┘   │
│                       ↓                              │
│  ┌──────────────────────────────────────────────┐   │
│  │          React Flight Renderer                │   │
│  │  • renderToFlightStream                       │   │
│  │  • 序列化 RSC Payload                         │   │
│  │  • 流式传输到客户端                           │   │
│  └──────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────┘

⚙️ 核心渲染流程

1. 请求解析 - 解析 headers,获取 FlightRouterState

2. 上下文创建 - 创建 AppRenderContext, WorkStore, RequestStore

3. 组件树构建 - 从 LoaderTree 创建 React 组件树

4. Flight 序列化 - 使用 React Flight 渲染器序列化

5. 流式响应 - 通过 ReadableStream 流式返回客户端

// app-render.tsx 核心入口
async function generateDynamicRSCPayload(ctx: AppRenderContext) {
  // 1. 解析 loader tree
  const { loaderTree } = ctx.componentMod.routeModule.userland;
  
  // 2. 构建组件树
  const flightData = await walkTreeWithFlightRouterState({
    ctx, loaderTreeToFilter: loaderTree, ...
  });
  
  // 3. 返回 RSC payload
  return { f: flightData, q: query, ... };
}

🔄 RSC vs RCC 对比

特性 Server Components Client Components
执行环境 服务器端 客户端(浏览器)
JavaScript 包 零客户端 JS 需要打包发送
数据获取 直接访问数据库/API 通过 fetch/AJAX
状态管理 无状态 useState/useReducer
交互性 无(纯展示) 事件处理/副作用
序列化格式 React Flight JSON/JS

📈 架构演进历史

Pages Router (Next.js 9-12)

  • getServerSideProps
  • getStaticProps
  • 页面级数据获取
  • JSON 序列化

App Router (Next.js 13)

  • 引入 RSC
  • Server Components 默认
  • 嵌套布局支持
  • 流式渲染

App Router (Next.js 14)

  • Server Actions
  • 部分预渲染 (PPR)
  • 改进的缓存
  • Turbopack 稳定

App Router (Next.js 15+)

  • Cache Components
  • Instant Validation
  • Staged Rendering
  • Runtime Prefetch

🔖 版本特性对比

版本 核心特性 渲染策略
Next.js 13 RSC 基础支持 全量服务端渲染
Next.js 14 Server Actions, PPR 部分预渲染
Next.js 15 Cache Components 分阶段渲染
Next.js 15+ Instant Validation 运行时预取 + 验证

关键演进:从全量渲染 → PPR 部分渲染 → Staged Rendering 分阶段渲染

📦 AppRenderContext 核心类型

// app-render.tsx
export type AppRenderContext = {
  sharedContext: AppSharedContext    // buildId, deploymentId
  workStore: WorkStore               // 静态生成状态
  url: ParsedRelativeUrl             // 解析后的 URL
  componentMod: AppPageModule        // 组件模块
  renderOpts: RenderOpts             // 渲染选项
  parsedRequestHeaders: ParsedRequestHeaders
  getDynamicParamFromSegment: GetDynamicParamFromSegment
  interpolatedParams: Params         // 路由参数
  query: NextParsedUrlQuery          // 查询参数
  isPrefetch: boolean                // 是否预取请求
  isPossibleServerAction: boolean    // 是否可能是 action
  requestTimestamp: number           // 请求时间戳
  flightRouterState?: FlightRouterState  // 客户端路由状态
  requestId: string                  // 请求 ID
  pagePath: string                   // 页面路径
  implicitTags: ImplicitTags         // 隐式缓存标签
}

🌳 LoaderTree 数据结构

// lib/app-dir-module.ts
export type LoaderTree = [
  segment: string,                    // 路由段
  parallelRoutes: {
    [key: string]: LoaderTree         // 并行路由(children, @modal 等)
  },
  components: {
    layout?: [() => Promise, string]
    page?: [() => Promise, string]
    loading?: [() => Promise, string]
    error?: [() => Promise, string]
    'not-found'?: [() => Promise, string]
    template?: [() => Promise, string]
  },
  staticSiblings?: Map | null
]

// 解析 LoaderTree
function parseLoaderTree(tree: LoaderTree) {
  const [segment, parallelRoutes, modules] = tree;
  const { layout, page, loading, error, notFound } = modules;
  return { segment, parallelRoutes, layout, page, ... };
}

🛫 FlightRouterState 客户端状态

// shared/lib/app-router-types.ts
export type FlightRouterState = [
  segment: string,              // 当前段
  parallelRoutes: {
    [key: string]: FlightRouterState
  },
  // 可选的额外信息
  refreshToken?: string,
  seedData?: CacheNodeSeedData,
  head?: ReactNode,
  isRootRender?: boolean,
  isInitial?: boolean
]

// 从请求头解析
function parseAndValidateFlightRouterState(
  header: string | undefined
): FlightRouterState | undefined {
  if (!header) return undefined;
  try {
    return JSON.parse(decodeURIComponent(header));
  } catch {
    return undefined;
  }
}

💾 CacheNodeSeedData 缓存数据

// shared/lib/app-router-types.ts
export type CacheNodeSeedData = [
  rsc: ReactNode,               // RSC 组件树
  parallelRoutes: {
    [key: string]: CacheNodeSeedData | null
  },
  loading: LoadingModuleData | null,
  isPartial: boolean,           // 是否部分响应
  varyParams: Promise | null  // Vary 参数
]

// 创建 seed data
function createSeedData(
  ctx: AppRenderContext,
  rsc: ReactNode,
  parallelRoutes: Record,
  loading: LoadingModuleData | null,
  isPossiblyPartialResponse: boolean,
  isRuntimePrefetchable: boolean,
  varyParamsAccumulator: VaryParamsAccumulator | null
): CacheNodeSeedData {
  return [rsc, parallelRoutes, null, isPossiblyPartialResponse, 
          varyParamsAccumulator ? getVaryParamsThenable(...) : null];
}

🔧 WorkStore 工作存储

// work-async-storage.external.ts
export type WorkStore = {
  route: string                  // 当前路由
  pagePath: string              // 页面路径
  isStaticGeneration: boolean   // 是否静态生成
  
  // 动态渲染控制
  forceDynamic: boolean         // 强制动态
  forceStatic: boolean          // 强制静态
  dynamicShouldError: boolean   // 动态是否报错
  
  // 缓存配置
  fetchCache?: string           // fetch 缓存策略
  
  // 动态使用追踪
  dynamicUsageDescription?: string
  dynamicUsageStack?: string
  invalidDynamicUsageError?: Error
  
  // fetch 指标
  fetchMetrics: FetchMetric[]
  
  // React Server 错误
  reactServerErrorsByDigest: Map
}

📨 RequestStore 请求存储

// work-unit-async-storage.external.ts
export type RequestStore = {
  type: 'request'
  
  // 请求级别的状态
  phase: 'render' | 'action'
  
  // Cookies 和 Headers
  cookies: RequestCookies
  mutableCookies: ResponseCookies
  headers: Headers
  
  // Draft Mode
  draftMode: { isEnabled: boolean }
  
  // 缓存信号
  cacheSignal?: CacheSignal
  
  // 暂存渲染控制器
  stagedRendering?: StagedRenderingController
  
  // 异步 API Promises
  asyncApiPromises?: AsyncApiPromises
  
  // Stale Time
  stale?: number
  
  // 预渲染恢复缓存
  prerenderResumeDataCache?: PrerenderResumeDataCache
  
  // Vary 参数累积器
  varyParamsAccumulator?: VaryParamsAccumulator
}

🎬 PrerenderStore 预渲染存储

// work-unit-async-storage.external.ts
export type PrerenderStoreModernRuntime = {
  type: 'prerender-runtime'
  phase: 'render' | 'prerender'
  
  // 根参数
  rootParams: Params
  implicitTags: ImplicitTags
  
  // 控制器
  controller: AbortController
  renderSignal: AbortSignal
  
  // 缓存信号
  cacheSignal: CacheSignal
  
  // 动态追踪
  dynamicTracking: DynamicTracking | null
  
  // 缓存配置
  revalidate: number
  expire: number
  stale: number
  tags: string[]
  
  // 恢复缓存
  renderResumeDataCache: RenderResumeDataCache | null
  prerenderResumeDataCache: PrerenderResumeDataCache | null
  
  // Headers/Cookies (运行时预渲染)
  headers?: Headers
  cookies?: RequestCookies
  draftMode?: { isEnabled: boolean }
}

🎭 StagedRenderingController 分阶段渲染

// staged-rendering.ts
export enum RenderStage {
  Before = 0,          // 渲染前
  EarlyStatic = 1,     // 早期静态
  Static = 2,          // 静态阶段
  EarlyRuntime = 3,    // 早期运行时
  Runtime = 4,         // 运行时阶段
  Dynamic = 5,         // 动态阶段
  Abandoned = 6        // 已放弃
}

export class StagedRenderingController {
  currentStage: RenderStage = RenderStage.Before
  private stageResolvers: Map void> = new Map()
  
  // 推进到下一阶段
  advanceStage(stage: RenderStage) {
    this.currentStage = stage;
    const resolver = this.stageResolvers.get(stage);
    if (resolver) resolver();
  }
  
  // 等待特定阶段
  waitForStage(stage: RenderStage): Promise {
    if (this.currentStage >= stage) return Promise.resolve();
    return new Promise(resolve => {
      this.stageResolvers.set(stage, resolve);
    });
  }
}

📄 RenderResult 渲染结果

// render-result.ts
export default class RenderResult {
  private result: ReadableStream | string | null
  private metadata: AppPageRenderResultMetadata
  
  constructor(
    result: ReadableStream | string | null,
    metadata: AppPageRenderResultMetadata = {}
  ) {
    this.result = result;
    this.metadata = metadata;
  }
  
  // 获取元数据
  getMeta(): AppPageRenderResultMetadata {
    return this.metadata;
  }
  
  // 转换为 ReadableStream
  toReadableStream(): ReadableStream {
    if (this.result instanceof ReadableStream) {
      return this.result;
    }
    // 字符串转换为流
    return createReadableStreamFromString(this.result || '');
  }
  
  // 元数据包含 fetchMetrics, headers, cookies 等
}

⚡ generateDynamicRSCPayload

// app-render.tsx - 核心入口函数
async function generateDynamicRSCPayload(
  ctx: AppRenderContext,
  options?: { actionResult?, skipPageRendering?, ... }
): Promise {
  let flightData: FlightData = '';
  
  const { componentMod: { routeModule: { userland: { loaderTree } } } } = ctx;
  
  if (!options?.skipPageRendering) {
    // 构建元数据组件
    const { Viewport, Metadata, MetadataOutlet } = 
      createMetadataComponents({ tree: loaderTree, ... });
    
    // 核心调用:遍历树并生成 Flight Data
    flightData = await walkTreeWithFlightRouterState({
      ctx, loaderTreeToFilter: loaderTree,
      flightRouterState: ctx.flightRouterState,
      rscHead, injectedCSS, injectedJS, ...
    });
  }
  
  // 返回 RSC Payload
  return { f: flightData, q: getRenderedSearch(query), ... };
}

🌳 createComponentTree 组件树构建

// create-component-tree.tsx
export function createComponentTree(props: {
  loaderTree: LoaderTree
  parentParams: Params
  injectedCSS: Set
  injectedJS: Set
  ctx: AppRenderContext
  ...
}): Promise {
  return getTracer().trace(
    NextNodeServerSpan.createComponentTree,
    () => createComponentTreeInternal(props, true)
  );
}

// 内部实现:递归构建组件树
async function createComponentTreeInternal(props, isRoot) {
  const { segment, parallelRoutes, modules } = parseLoaderTree(tree);
  
  // 1. 加载 layout/page/error/loading 等模块
  const [LayoutOrPage, layoutStyles, layoutScripts] = 
    await createComponentStylesAndScripts({ ... });
  
  // 2. 处理动态参数
  const segmentParam = getDynamicParamFromSegment(tree);
  
  // 3. 递归处理并行路由
  for (const [key, route] of Object.entries(parallelRoutes)) {
    const childSeedData = await createComponentTreeInternal({
      loaderTree: route, ...
    });
  }
  
  // 4. 创建 seed data
  return createSeedData(ctx, element, parallelRoutes, loading, ...);
}

✈️ renderToFlightStream Flight 序列化

// stream-ops.ts
export function renderToFlightStream(
  componentMod: AppPageModule,
  rscPayload: RSCPayload,
  clientModules: ClientReferenceManifest,
  options: {
    onError: (err: unknown) => string | undefined
    filterStackFrame?: (frame: string) => boolean
    debugChannel?: DebugChannelServer
  }
): ReadableStream {
  // 使用 React Server DOM Webpack 的 renderToReadableStream
  const { renderToReadableStream } = componentMod;
  
  return renderToReadableStream(
    rscPayload,
    clientModules.clientModules,
    {
      onError: options.onError,
      filterStackFrame: options.filterStackFrame,
      environmentName: () => 'Server',
      debugChannel: options.debugChannel,
    }
  );
}

// React Flight 格式特点:
// 1. 引用 ID 系统 - 避免重复传输
// 2. 模块引用 - 客户端按需加载
// 3. 流式传输 - 边渲染边发送
// 4. Promise 支持 - 异步数据流式

🚶 walkTreeWithFlightRouterState 树遍历

// walk-tree-with-flight-router-state.tsx
export async function walkTreeWithFlightRouterState({
  ctx,
  loaderTreeToFilter,
  parentParams,
  flightRouterState,
  rscHead,
  injectedCSS,
  injectedJS,
  ...
}): Promise {
  // 1. 如果有客户端路由状态,只渲染差异部分
  if (flightRouterState) {
    // 找到公共前缀,只渲染变化的部分
    return walkTreeWithDiff({ ... });
  }
  
  // 2. 完整渲染
  const seedData = await createComponentTree({
    loaderTree: loaderTreeToFilter,
    parentParams,
    injectedCSS,
    injectedJS,
    ctx,
    ...
  });
  
  // 3. 返回 Flight Data Path
  return [[segment, parallelRoutes, seedData, ...]];
}

// 关键:根据 flightRouterState 决定渲染范围
// - 无状态:渲染整个树
// - 有状态:只渲染变化的部分(增量更新)

🔍 parseLoaderTree 解析加载树

// shared/lib/router/utils/parse-loader-tree.ts
export function parseLoaderTree(tree: LoaderTree): {
  segment: string
  parallelRoutes: { [key: string]: LoaderTree }
  modules: {
    layout?: LoadingModuleData
    page?: LoadingModuleData
    template?: LoadingModuleData
    error?: LoadingModuleData
    loading?: LoadingModuleData
    'not-found'?: LoadingModuleData
    forbidden?: LoadingModuleData
    unauthorized?: LoadingModuleData
  }
  conventionPath?: string
} {
  const [segment, parallelRoutes, modules] = tree;
  
  // 确定约定路径(layout/page/error 等)
  let conventionPath: string | undefined;
  if (modules.layout) conventionPath = getLayoutPath(modules.layout[1]);
  else if (modules.page) conventionPath = getPagePath(modules.page[1]);
  
  return { segment, parallelRoutes, modules, conventionPath };
}

// LoaderTree 结构:[segment, parallelRoutes, modules, staticSiblings]
// parallelRoutes 包含 children 和其他命名槽(@modal, @sidebar 等)

🎯 getDynamicParamFromSegment 动态参数

// app-render.tsx
function makeGetDynamicParamFromSegment(
  interpolatedParams: Params,
  fallbackRouteParams: OpaqueFallbackRouteParams | null,
  optimisticRouting: boolean
): GetDynamicParamFromSegment {
  return function getDynamicParamFromSegment(loaderTree: LoaderTree) {
    const [segment, , , staticSiblings] = loaderTree;
    
    // 解析段参数(如 [id], [...slug], [[...catchall]])
    const segmentParam = getSegmentParam(segment);
    if (!segmentParam) return null;
    
    const { paramName, paramType } = segmentParam;
    const dynamicParamType = dynamicParamTypes[paramType];
    
    // 获取参数值
    const siblings = optimisticRouting ? staticSiblings : null;
    return getDynamicParam(
      interpolatedParams,
      paramName,
      dynamicParamType,
      fallbackRouteParams,
      siblings
    );
  };
}

// 动态参数类型映射:
// 'id' → 'd' (动态)
// '[...slug]' → 'c' (捕获所有)
// '[[...slug]]' → 'oc' (可选捕获所有)

🔮 prospectiveRuntimeServerPrerender 预渲染

// app-render.tsx
async function prospectiveRuntimeServerPrerender(
  ctx: AppRenderContext,
  getPayload: () => any,
  prerenderResumeDataCache: PrerenderResumeDataCache | null,
  renderResumeDataCache: RenderResumeDataCache | null,
  rootParams: Params,
  headers, cookies, draftMode
) {
  // 1. 创建预渲染控制器
  const prerenderController = new AbortController();
  const renderController = new AbortController();
  const cacheSignal = new CacheSignal();
  
  // 2. 创建预渲染存储
  const prerenderStore: PrerenderStoreModernRuntime = {
    type: 'prerender-runtime',
    phase: 'render',
    rootParams,
    controller: prerenderController,
    renderSignal: renderController.signal,
    cacheSignal,
    ...
  };
  
  // 3. 执行预渲染
  const payload = await workUnitAsyncStorage.run(prerenderStore, getPayload);
  const pendingResult = getServerPrerender(ComponentMod)(payload, ...);
  
  // 4. 等待缓存填充
  await cacheSignal.cacheReady();
  
  // 5. 中止预渲染
  renderController.abort();
  prerenderController.abort();
  
  return createReactServerPrerenderResult(pendingResult);
}

🏁 finalRuntimeServerPrerender 最终预渲染

// app-render.tsx
async function finalRuntimeServerPrerender(
  ctx: AppRenderContext,
  getPayload: () => any,
  prerenderResumeDataCache: PrerenderResumeDataCache,
  renderResumeDataCache: RenderResumeDataCache | null,
  rootParams: Params,
  headers, cookies, draftMode,
  onError: (err: unknown) => string | undefined,
  staleTimeIterable: StaleTimeIterable
) {
  const finalPrerenderController = new AbortController();
  
  // 使用预填充的缓存进行最终渲染
  const finalPrerenderStore: PrerenderStoreModernRuntime = {
    type: 'prerender-runtime',
    phase: 'render',
    rootParams,
    controller: finalPrerenderController,
    renderSignal: finalPrerenderController.signal,
    cacheSignal: null,  // 不需要追踪缓存
    prerenderResumeDataCache,
    renderResumeDataCache,
    ...
  };
  
  const payload = await workUnitAsyncStorage.run(finalPrerenderStore, getPayload);
  const result = getClientPrerender(ComponentMod)(payload, ...);
  
  return { result, staleTimeIterable };
}

🎬 handleAction Server Action 处理

// action-handler.ts
export async function handleAction({
  req,
  res,
  ctx,
  requestStore,
  serverActions,
  workStore,
}: {
  req: BaseNextRequest
  res: BaseNextResponse
  ctx: AppRenderContext
  requestStore: RequestStore
  serverActions: Map
  workStore: WorkStore
}): Promise {
  // 1. 检查是否是 Server Action 请求
  const actionId = getServerActionId(req);
  if (!actionId) return undefined;
  
  // 2. 获取 Action 函数
  const action = serverActions.get(actionId);
  if (!action) {
    throw new Error(`Server Action "${actionId}" not found`);
  }
  
  // 3. 解析 Action 参数
  const args = await parseActionArgs(req);
  
  // 4. 执行 Action
  const result = await workUnitAsyncStorage.run(requestStore, () => {
    return action(...args);
  });
  
  // 5. 处理重定向和错误
  if (isRedirectError(result)) {
    const redirectUrl = getURLFromRedirectError(result);
    res.setHeader('Location', redirectUrl);
    res.statusCode = getRedirectStatusCodeFromError(result);
  }
  
  return result;
}

📋 createMetadataComponents 元数据组件

// metadata-context.ts
export function createMetadataComponents({
  tree,
  parsedQuery,
  pathname,
  metadataContext,
  interpolatedParams,
  serveStreamingMetadata,
  isRuntimePrefetchable,
}: {
  tree: LoaderTree
  parsedQuery: ParsedUrlQuery
  pathname: string
  metadataContext: MetadataContext
  interpolatedParams: Params
  serveStreamingMetadata: boolean
  isRuntimePrefetchable: boolean
}): {
  Viewport: ComponentType
  Metadata: ComponentType
  MetadataOutlet: ComponentType | null
} {
  // 创建元数据上下文
  const context = createMetadataContext(metadataContext);
  
  // 解析元数据
  const metadata = resolveMetadata(tree, interpolatedParams, pathname);
  
  // 创建 Viewport 组件
  const Viewport = () => {
    return createElement('meta', { name: 'viewport', content: metadata.viewport });
  };
  
  // 创建 Metadata 组件
  const Metadata = () => {
    return createElement(Fragment, null, 
      metadata.title && createElement('title', null, metadata.title),
      ...renderMetaTags(metadata)
    );
  };
  
  // 流式元数据 Outlet(用于延迟加载的元数据)
  const MetadataOutlet = serveStreamingMetadata 
    ? createMetadataOutlet(metadata) 
    : null;
  
  return { Viewport, Metadata, MetadataOutlet };
}

⚠️ createReactServerErrorHandler 错误处理

// create-error-handler.ts
export function createReactServerErrorHandler(
  isDev: boolean,
  isBuildTimePrerendering: boolean,
  reactServerErrorsByDigest: Map,
  onInstrumentationRequestError?: OnInstrumentationRequestError
): (err: unknown) => string | undefined {
  return function onError(err: unknown): string | undefined {
    // 1. 检查是否是已知错误
    const digest = getDigestForWellKnownError(err);
    if (digest) return digest;
    
    // 2. 生成错误摘要(用于客户端显示)
    const errorDigest = generateErrorDigest(err);
    
    // 3. 存储错误详情(用于服务端日志)
    const digestedError: DigestedError = {
      digest: errorDigest,
      error: err,
      stack: getStackWithoutErrorMessage(err),
    };
    reactServerErrorsByDigest.set(errorDigest, digestedError);
    
    // 4. 上报错误
    if (onInstrumentationRequestError && !isUserLandError(err)) {
      onInstrumentationRequestError(err, ...);
    }
    
    // 5. 开发环境打印详情
    if (isDev) {
      console.error('Server Error:', err);
    }
    
    return errorDigest;
  };
}

🏭 设计模式:工厂模式

// Store 工厂函数
export function createWorkStore(options: WorkStoreOptions): WorkStore {
  return {
    route: options.route,
    pagePath: options.pagePath,
    isStaticGeneration: options.isStaticGeneration ?? false,
    forceDynamic: false,
    forceStatic: false,
    dynamicShouldError: false,
    fetchMetrics: [],
    reactServerErrorsByDigest: new Map(),
  };
}

export function createRequestStore(options: RequestStoreOptions): RequestStore {
  return {
    type: 'request',
    phase: 'render',
    cookies: new RequestCookies(options.headers),
    mutableCookies: new ResponseCookies(options.headers),
    headers: options.headers,
    draftMode: { isEnabled: options.draftMode ?? false },
  };
}

// 使用
const workStore = createWorkStore({ route, pagePath, isStaticGeneration });
const requestStore = createRequestStore({ headers, cookies });

🎯 设计模式:策略模式

// 渲染策略选择
type RenderStrategy = 'static' | 'dynamic' | 'ppr' | 'runtime-prefetch';

function selectRenderStrategy(
  workStore: WorkStore,
  requestStore: RequestStore,
  experimental: ExperimentalConfig
): RenderStrategy {
  // 策略 1: 强制动态
  if (workStore.forceDynamic) return 'dynamic';
  
  // 策略 2: PPR 部分预渲染
  if (experimental.isRoutePPREnabled && workStore.isStaticGeneration) {
    return 'ppr';
  }
  
  // 策略 3: 静态生成
  if (workStore.isStaticGeneration) return 'static';
  
  // 策略 4: 运行时预取
  if (requestStore.stagedRendering && hasRuntimePrefetch) {
    return 'runtime-prefetch';
  }
  
  // 默认: 动态渲染
  return 'dynamic';
}

// 不同策略使用不同的渲染函数
const renderer = renderStrategies[strategy];
return renderer(ctx, requestStore);

👁️ 设计模式:观察者模式

// CacheSignal - 缓存就绪信号
export class CacheSignal {
  private listeners: Set<() => void> = new Set();
  private pendingCount: number = 0;
  
  // 订阅缓存就绪事件
  cacheReady(): Promise {
    if (this.pendingCount === 0) return Promise.resolve();
    return new Promise(resolve => {
      this.listeners.add(resolve);
    });
  }
  
  // 开始追踪
  begin() { this.pendingCount++; }
  
  // 结束追踪
  end() {
    this.pendingCount--;
    if (this.pendingCount === 0) {
      // 通知所有监听者
      this.listeners.forEach(listener => listener());
      this.listeners.clear();
    }
  }
}

// 使用
cacheSignal.begin();
fetchData().then(() => cacheSignal.end());
await cacheSignal.cacheReady();  // 等待所有缓存填充完成

🔗 设计模式:责任链模式

// 中间件链
type Middleware = (
  req: BaseNextRequest,
  res: BaseNextResponse,
  next: () => Promise
) => Promise;

// 构建中间件链
function composeMiddleware(middlewares: Middleware[]): Middleware {
  return async (req, res, next) => {
    let index = 0;
    
    const dispatch = async (): Promise => {
      if (index >= middlewares.length) {
        return next();
      }
      const middleware = middlewares[index++];
      return middleware(req, res, dispatch);
    };
    
    return dispatch();
  };
}

// Next.js 内部中间件链
const middlewareChain = composeMiddleware([
  // 1. 请求解析
  parseRequestMiddleware,
  // 2. 缓存检查
  cacheCheckMiddleware,
  // 3. 认证检查
  authMiddleware,
  // 4. 渲染
  renderMiddleware,
]);

📐 架构 UML 类图

┌─────────────────┐     ┌──────────────────┐
│ AppRenderContext│────▶│    WorkStore     │
├─────────────────┤     ├──────────────────┤
│ +sharedContext  │     │ +route           │
│ +workStore      │     │ +forceDynamic    │
│ +url            │     │ +fetchMetrics    │
│ +componentMod   │     └──────────────────┘
│ +renderOpts     │              │
└─────────────────┘              ▼
         │              ┌──────────────────┐
         │              │  RequestStore    │
         │              ├──────────────────┤
         ▼              │ +cookies         │
┌─────────────────┐     │ +headers         │
│   LoaderTree    │     │ +draftMode       │
├─────────────────┤     └──────────────────┘
│ +segment        │              │
│ +parallelRoutes │              ▼
│ +modules        │     ┌──────────────────┐
└─────────────────┘     │StagedRendering   │
         │              ├──────────────────┤
         ▼              │ +currentStage    │
┌─────────────────┐     │ +advanceStage()  │
│CacheNodeSeedData│     │ +waitForStage()  │
├─────────────────┤     └──────────────────┘
│ +rsc            │
│ +parallelRoutes │
│ +loading        │
│ +isPartial      │
└─────────────────┘

⏱️ 渲染时序图

Client          Next.js Server        React Flight        WorkStore
  │                   │                     │                  │
  │───Request────────▶│                     │                  │
  │                   │                     │                  │
  │                   ├──parseRequest()     │                  │
  │                   │                     │                  │
  │                   ├──createContext()───▶│                  │
  │                   │                     │                  │
  │                   │                   ├──createStore()────▶│
  │                   │                     │                  │
  │                   ├──generatePayload()  │                  │
  │                   │                     │                  │
  │                   │   ┌─────────────────┤                  │
  │                   │   │createComponentTree()               │
  │                   │   └─────────────────┤                  │
  │                   │                     │                  │
  │                   │                   ├──renderToFlight()─▶│
  │                   │                     │                  │
  │◀──Flight Stream───┼─────────────────────┤                  │
  │                   │                     │                  │
  │───Parse Flight──▶│                     │                  │
  │                   │                     │                  │
  │───Hydrate────────▶│                     │                  │

🌊 数据流图

┌─────────────────────────────────────────────────────────┐
│                     Request Flow                        │
└─────────────────────────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│  1. Parse Headers                                       │
│     - NEXT_ROUTER_STATE_TREE_HEADER                     │
│     - NEXT_ROUTER_PREFETCH_HEADER                       │
│     - RSC_HEADER                                        │
└─────────────────────────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│  2. Create Context                                      │
│     AppRenderContext → WorkStore → RequestStore         │
└─────────────────────────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│  3. Build Component Tree                                │
│     LoaderTree → parseLoaderTree → createComponentTree  │
└─────────────────────────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│  4. Serialize to Flight                                 │
│     RSC Payload → renderToFlightStream → ReadableStream │
└─────────────────────────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│  5. Stream Response                                     │
│     FlightRenderResult → chunked response               │
└─────────────────────────────────────────────────────────┘

🌲 组件树构建流程

LoaderTree (输入)
    │
    ▼
┌─────────────────────────────────┐
│ parseLoaderTree(tree)           │
│ - segment: 'blog/[slug]'        │
│ - parallelRoutes: { children }  │
│ - modules: { layout, page }     │
└─────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────┐
│ getLayoutOrPageModule(tree)     │
│ - 加载 layout.tsx 模块          │
│ - 加载 page.tsx 模块            │
│ - 提取样式和脚本                │
└─────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────┐
│ 处理动态参数                    │
│ - getDynamicParamFromSegment()  │
│ - params = { slug: 'hello' }    │
└─────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────┐
│ 递归处理并行路由                │
│ - for (key in parallelRoutes)   │
│ - createComponentTree(child)    │
└─────────────────────────────────┘
    │
    ▼
CacheNodeSeedData (输出)

📦 缓存策略流程

┌────────────────────────────────────────────────────┐
│                 Cache Strategy                     │
├────────────────────────────────────────────────────┤
│                                                    │
│  1. Check Full Route Cache                        │
│     └─▶ Hit? Return cached response               │
│                                                    │
│  2. Check Data Cache                              │
│     └─▶ Hit? Return cached data                   │
│                                                    │
│  3. Check Full Route Cache (Prerendered)          │
│     └─▶ Hit? Return static HTML                   │
│                                                    │
│  4. Dynamic Render                                │
│     ├─▶ Create WorkStore + RequestStore           │
│     ├─▶ Build Component Tree                      │
│     ├─▶ Serialize to Flight                       │
│     └─▶ Stream response                           │
│                                                    │
│  5. Update Cache (if revalidate set)              │
│     ├─▶ Store in Data Cache                       │
│     └─▶ Store in Full Route Cache                 │
│                                                    │
└────────────────────────────────────────────────────┘

🌊 流式渲染优化

传统 SSR

请求 ──────▶ 完整渲染 ──────▶ 响应
         │              │
         │  等待所有    │
         │  数据加载    │
         │              │
         └──────────────┘
         首字节时间 (TTFB) 长

流式 RSC

请求 ─▶ 立即响应 ─▶ 流式传输
       │         │
       │  Shell  │  数据
       │  立即    │  增量
       │  返回    │  到达
       │         │
       └─────────┘
       TTFB 极短

关键优势:Shell 立即返回 + Suspense 边界渐进填充

⚡ PPR 增量渲染

// PPR (Partial Prerendering) 流程

┌─────────────────────────────────────────────────────┐
│  Static Shell (预渲染)                              │
│  ┌───────────────────────────────────────────────┐  │
│  │  Header, Footer, Layout                       │  │
│  │  ┌─────────────────────────────────────────┐  │  │
│  │  │  <Suspense fallback={<Loading />}>      │  │  │
│  │  │    {await fetchDynamicData()}            │  │  │
│  │  │  </Suspense>                             │  │  │
│  │  └─────────────────────────────────────────┘  │  │
│  └───────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────┘
                        │
                        ▼ (运行时)
┌─────────────────────────────────────────────────────┐
│  Dynamic Holes (运行时填充)                         │
│  - 异步数据加载完成后替换 fallback                  │
│  - 不阻塞静态部分的传输                             │
│  - 客户端可以开始渲染静态部分                       │
└─────────────────────────────────────────────────────┘

// PPR 配置
export const experimental = {
  ppr: 'incremental',  // 启用增量 PPR
};

💾 内存管理优化

// 内存优化策略

// 1. 流式处理 - 避免 Buffer 累积
async function* streamResponse() {
  for await (const chunk of renderStream) {
    yield chunk;  // 立即发送,不累积
  }
}

// 2. 弱引用缓存 - 允许 GC 回收
const moduleCache = new WeakMap();

// 3. 惰性加载 - 按需加载模块
const pageModule = await import(/* webpackMode: "lazy" */ './page');

// 4. 引用 ID 去重
// React Flight 使用 ID 引用,避免重复传输
const references = new Map();

// 5. 及时清理
workStore.reactServerErrorsByDigest.clear();
prerenderResumeDataCache.clear();

// 6. 限制缓存大小
const MAX_CACHE_SIZE = 100 * 1024 * 1024; // 100MB
if (cache.size > MAX_CACHE_SIZE) {
  evictOldest(cache);
}

🔄 并行处理优化

// 并行加载组件模块
const parallelRouteMap = await Promise.all(
  Object.keys(parallelRoutes).map(async (key) => {
    const route = parallelRoutes[key];
    const seedData = await createComponentTreeInternal({
      loaderTree: route,
      parentParams: currentParams,
      ...
    });
    return [key, seedData];
  })
);

// 并行预加载资源
await Promise.all([
  preloadCSS(injectedCSS),
  preloadJS(injectedJS),
  preloadFonts(injectedFontPreloadTags),
]);

// 并行处理元数据
const [viewport, metadata] = await Promise.all([
  resolveViewport(tree),
  resolveMetadata(tree),
]);

// 使用 runInSequentialTasks 进行阶段控制
const result = await runInSequentialTasks(
  () => stageController.advanceStage(RenderStage.Static),
  () => stageController.advanceStage(RenderStage.Dynamic)
);

✅ 最佳实践

组件设计

  • 默认使用 Server Components
  • 交互部分用 'use client'
  • 保持 Server Components 纯净
  • 避免在 Server 组件中 useState

数据获取

  • 直接在组件中 async/await
  • 利用 fetch 自动去重
  • 使用 Suspense 边界
  • 合理设置 revalidate

性能优化

  • 使用 loading.tsx 加载状态
  • 并行路由优化布局
  • 利用 Partial Prerendering
  • 启用 Turbopack 构建

错误处理

  • 提供 error.tsx 边界
  • 使用 global-error.tsx
  • 实现 not-found.tsx
  • 日志记录和监控

❌ 常见反模式

❌ 错误 1:在 Server Component 中使用客户端 hooks

// ❌ 错误
export default async function Page() {
  const [state, setState] = useState(); // 报错!
}

❌ 错误 2:传递不可序列化的 props

// ❌ 错误
<ClientComponent onClick={() => {}} /> // 函数不可序列化

❌ 错误 3:过度使用 'use client'

// ❌ 错误 - 整个文件都变成客户端组件
'use client';
export function formatDate() { ... } // 纯函数,不需要客户端

🔍 调试技巧

// 1. 启用 React Flight 调试
NEXT_DEBUG_RSC=1 npm run dev

// 2. 查看组件边界
// React DevTools 会标记 Server/Client 边界

// 3. 日志追踪
export default async function Page() {
  console.log('Server Component executing');
  const data = await fetchData();
  return <div>{data}</div>;
}

// 4. 使用 debug channel(开发模式)
const debugChannel = createDebugChannel();
setReactDebugChannel(debugChannel.clientSide, requestId);

// 5. 错误摘要查看
// 检查 reactServerErrorsByDigest Map

// 6. 性能分析
const start = performance.now();
await createComponentTree(...);
console.log(`Component tree took ${performance.now() - start}ms`);

⚡ 性能优化清单

优化项 技术 收益
流式渲染 Suspense + Flight Stream TTFB 降低 50%+
部分预渲染 PPR 静态内容立即返回
代码分割 Client Components 自动分割 包体积减少 30-70%
缓存策略 fetch cache + Data Cache 重复请求避免
并行加载 Promise.all 加载时间减少
Turbopack Rust 编译器 构建速度 700x

🔬 与其他框架对比

特性 Next.js RSC Remix Astro
服务端组件 ✅ 完整支持 ❌ loaders ✅ Islands
流式渲染 ✅ 原生 ✅ defer ⚠️ 有限
客户端 hydration 选择性 全量 Islands
数据获取 组件内 async loaders 组件内 async
嵌套布局 ✅ 原生 ✅ 原生 ⚠️ 有限
生态成熟度 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐

🚀 未来趋势

短期 (2026)

  • PPR 默认启用
  • Cache Components 稳定
  • Instant Validation 生产可用
  • 改进的调试工具

中期 (2027)

  • Edge Runtime 完整支持
  • 更细粒度的缓存控制
  • AI 辅助代码分割

长期 (2028+)

  • 分布式渲染
  • 跨服务组件共享
  • 自动性能优化
  • 更智能的预取策略

研究方向

  • 服务端状态管理
  • 实时协作渲染
  • 边缘 AI 推理集成

📚 扩展阅读

官方文档

  • Next.js App Router 文档
  • React Server Components RFC
  • Vercel Blog - RSC 深度解析

源码位置

  • packages/next/src/server/app-render/
  • packages/next/src/shared/lib/app-router-types.ts
  • packages/next/src/server/lib/app-dir-module.ts

相关技术

  • React Flight 协议
  • Turbopack 架构
  • Vercel Edge Runtime

📝 总结

核心要点

  1. AppRenderContext 是渲染的核心上下文
  2. LoaderTree 表示路由组件树结构
  3. FlightRouterState 实现增量更新
  4. StagedRendering 控制渲染阶段
  5. React Flight 序列化 RSC Payload

关键流程

请求 → 解析 → 创建上下文 → 构建组件树 → Flight 序列化 → 流式响应

性能关键

流式渲染 + PPR + 缓存策略 + 并行处理 = 极致性能

🙏 致谢

本 PPT 基于以下项目源码深度分析:

  • Next.js - Vercel 团队
  • React - Meta 团队
  • React Server Components - React 团队

特别感谢

  • Next.js 开源社区
  • React 核心团队
  • Vercel 工程团队

生成日期: 2026-03-17 | 技术深度解读系列

📖 附录:API 速查表

API 用途 位置
generateDynamicRSCPayload 生成 RSC Payload app-render.tsx
createComponentTree 构建组件树 create-component-tree.tsx
renderToFlightStream Flight 序列化 stream-ops.ts
parseLoaderTree 解析加载树 parse-loader-tree.ts
StagedRenderingController 分阶段渲染控制 staged-rendering.ts
CacheSignal 缓存就绪信号 cache-signal.ts
handleAction Server Action 处理 action-handler.ts