基于 Next.js 15+ 源码深度解读
2026-03-17 | 技术深度解读
第一部分:基础架构
第二部分:演进历史
第三部分:核心类解析
第四部分:核心函数
React Server Components (RSC) 是 React 的一种新组件类型,在服务器端渲染,零客户端 JavaScript。
核心特性
解决的问题
┌─────────────────────────────────────────────────────┐
│ 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, ... };
}
| 特性 | Server Components | Client Components |
|---|---|---|
| 执行环境 | 服务器端 | 客户端(浏览器) |
| JavaScript 包 | 零客户端 JS | 需要打包发送 |
| 数据获取 | 直接访问数据库/API | 通过 fetch/AJAX |
| 状态管理 | 无状态 | useState/useReducer |
| 交互性 | 无(纯展示) | 事件处理/副作用 |
| 序列化格式 | React Flight | JSON/JS |
Pages Router (Next.js 9-12)
App Router (Next.js 13)
App Router (Next.js 14)
App Router (Next.js 15+)
| 版本 | 核心特性 | 渲染策略 |
|---|---|---|
| Next.js 13 | RSC 基础支持 | 全量服务端渲染 |
| Next.js 14 | Server Actions, PPR | 部分预渲染 |
| Next.js 15 | Cache Components | 分阶段渲染 |
| Next.js 15+ | Instant Validation | 运行时预取 + 验证 |
关键演进:从全量渲染 → PPR 部分渲染 → Staged Rendering 分阶段渲染
// 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 // 隐式缓存标签
}
// 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, ... };
}
// 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;
}
}
// 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];
}
// 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
}
// 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
}
// 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 }
}
// 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);
});
}
}
// 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 等
}
// 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), ... };
}
// 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, ...);
}
// 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 支持 - 异步数据流式
// 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 决定渲染范围
// - 无状态:渲染整个树
// - 有状态:只渲染变化的部分(增量更新)
// 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 等)
// 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' (可选捕获所有)
// 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);
}
// 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 };
}
// 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;
}
// 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 };
}
// 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,
]);
┌─────────────────┐ ┌──────────────────┐
│ 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 (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
// 并行加载组件模块
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)
);
组件设计
数据获取
性能优化
错误处理
❌ 错误 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)
中期 (2027)
长期 (2028+)
研究方向
官方文档
源码位置
相关技术
核心要点
关键流程
请求 → 解析 → 创建上下文 → 构建组件树 → Flight 序列化 → 流式响应
性能关键
流式渲染 + PPR + 缓存策略 + 并行处理 = 极致性能
本 PPT 基于以下项目源码深度分析:
特别感谢
生成日期: 2026-03-17 | 技术深度解读系列
| 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 |