facebook/reactMITd083ec1Report / request removal

Server Components (Flight)

Flight is the wire protocol and client runtime for transferring a server-rendered component model to a client. The server creates rendering tasks, serializes models into rows, and flushes completed chunks; the client stores those chunks and exposes the root as a thenable.

It exists because the client needs more than markup: the payload can contain model references, lazy references, module references, text, binary data, streams, and errors. The client therefore reconstructs values from an incremental protocol instead of merely parsing HTML.

Sources: packages/react-server/src/ReactFlightServer.js:2863-2888, packages/react-server/src/ReactFlightServer.js:6307-6439, packages/react-server/src/ReactFlightServer.js:6795-6813, packages/react-client/src/ReactFlightClient.js:487-491, packages/react-server/src/ReactFlightServer.js:3073-3075, packages/react-server/src/ReactFlightServer.js:3077-3079, packages/react-client/src/ReactFlightClient.js:5650-5656, packages/react-client/src/ReactFlightClient.js:3372-3396, packages/react-server/src/ReactFlightServer.js:4597-4673

Core concepts

Flight row

A Flight row is an incrementally framed record whose identifier is hexadecimal and whose payload may be JSON, a reference, text, binary data, or an error.

Sources: packages/react-server/src/ReactFlightServer.js:3157-3159, packages/react-server/src/ReactFlightServer.js:3161-3169, packages/react-server/src/ReactFlightServer.js:5194-5230, packages/react-server/src/ReactFlightServer.js:4597-4673

Chunk

A chunk is the client-side promise-like state associated with one row identifier. It can be pending, blocked, resolved, initialized, errored, or halted.

Sources: packages/react-client/src/ReactFlightClient.js:155, packages/react-client/src/ReactFlightClient.js:161, packages/react-client/src/ReactFlightClient.js:162, packages/react-client/src/ReactFlightClient.js:164, packages/react-client/src/ReactFlightClient.js:165, packages/react-client/src/ReactFlightClient.js:170

Model reference

A model reference is a compact string pointing to another row identifier; ordinary references use $ plus hexadecimal digits, while lazy references use $L plus hexadecimal digits.

Sources: packages/react-server/src/ReactFlightServer.js:3073-3075, packages/react-server/src/ReactFlightServer.js:3077-3079

Server Component

A Server Component is represented here as server-side model work that becomes serialized data and references, rather than as a distinct reconciler work tag. The shown reconciler tag list includes FunctionComponent, ClassComponent, and HostComponent, while the Flight server renders component models through tasks.

Sources: packages/react-reconciler/src/getComponentNameFromFiber.js:19-50, packages/react-server/src/ReactFlightServer.js:6307-6439

How Flight frames a streamed model

The server assigns each task a new chunk identifier through createTask, which increments request.nextChunkId and delegates to createTaskWithID. A row header is then formed as hexadecimal ID, a colon, and a tag; reference rows append JSON and a newline.

The payload is therefore a structured stream rather than plain HTML. JSON is the base representation through stringify, but the protocol adds row identifiers, special reference strings, and length-framed content. Text rows use a T tag followed by a hexadecimal byte length and comma, while binary rows use the same length framing and place the header and content next to each other.

EncodingWire shapePurpose
ModelID, JSON payload, newlineCarries serialized model data.
ReferenceJSON string such as $ plus an IDPoints to another row.
Lazy referenceJSON string such as $L plus an IDDefers another row through a lazy value.
TextID, T, hexadecimal length, comma, bytesTransfers text without treating it as ordinary JSON.
BinaryID, tag, hexadecimal length, comma, bytesTransfers typed-array or other binary content.
ErrorE row with serialized error informationCommunicates a recoverable server error.

The server preserves framing under backpressure by placing an atomic sentinel before a text or binary header/content pair; otherwise another chunk could be inserted between the two pieces and corrupt row boundaries.

Flight row dataflow — How does a server model become client-readable data?

Evidence

Sources: packages/react-server/src/ReactFlightServer.js:2863-2888, packages/react-server/src/ReactFlightServer.js:3157-3159, packages/react-server/src/ReactFlightServer.js:3161-3169, packages/react-server/src/ReactFlightServer.js:494, packages/react-client/src/ReactFlightClient.js:5650-5656, packages/react-server/src/ReactFlightServer.js:5194-5230, packages/react-server/src/ReactFlightServer.js:5143-5192, packages/react-server/src/ReactFlightServer.js:3073-3075, packages/react-server/src/ReactFlightServer.js:3077-3079, packages/react-server/src/ReactFlightServer.js:4597-4673

How the client reconstructs the element tree

The client first exposes the root by unwrapping the response and retrieving chunk 0. If the identifier is not present, getChunk creates a pending chunk, or creates an error or halted chunk when the response has already closed.

When a model row arrives, resolveModelChunk stores the model, marks the chunk RESOLVED_MODEL, and initializes it immediately when listeners are waiting. initializeModelChunk changes the chunk to BLOCKED before parsing, then calls parseModel; this temporary state prevents recursive or cyclic references from being initialized inconsistently.

parseModel calls JSON.parse and then reviveModel, so deserialization is not just ordinary JSON parsing: the reviver resolves the protocol’s special values and references. References are later fulfilled by walking their recorded object path; if a referenced chunk is still pending, the reference is attached as a listener to that dependency.

Once parsing completes, wakeChunk calls waiting functions or fulfills waiting references, then transfers development debug information into the initialized value. A lazy wrapper can hold a chunk and use readChunk as its initializer; resolveLazy repeatedly unwraps initialized lazy payloads until it reaches the actual value.

Modules follow a separate path: initializeModuleChunk calls requireModule, then stores the resulting value and marks the module chunk INITIALIZED. This is why the protocol can reconstruct an element tree containing client-side module references instead of sending executable component source as HTML.

The client also handles cycles explicitly. resolveBlockedCycle detects when a reference points back to the chunk currently being initialized, and wakeChunkIfInitialized can fulfill that reference with the already available handler value.

Client reconstruction sequence — How does the client turn streamed rows into a root value?

Evidence

If the stream closes with unresolved chunks, the client either halts pending chunks when partial streams are allowed or reports a global error. Server-side failures are encoded as error rows containing a digest and, in development, error metadata such as name, message, stack, environment, and owner references.

Sources: packages/react-client/src/ReactFlightClient.js:487-491, packages/react-client/src/ReactFlightClient.js:1658-1678, packages/react-client/src/ReactFlightClient.js:949-977, packages/react-client/src/ReactFlightClient.js:1133-1271, packages/react-client/src/ReactFlightClient.js:5650-5656, packages/react-client/src/ReactFlightClient.js:1751-1939, packages/react-client/src/ReactFlightClient.js:660-678, packages/react-client/src/ReactFlightClient.js:1632-1656, packages/react-client/src/ReactFlightClient.js:2253-2268, packages/react-client/src/ReactFlightClient.js:1273-1285, packages/react-client/src/ReactFlightClient.js:695-720, packages/react-client/src/ReactFlightClient.js:722-800, packages/react-client/src/ReactFlightClient.js:5702-5739, packages/react-server/src/ReactFlightServer.js:4597-4673

How a Server Component differs from reconciler component kinds

The Flight server’s unit of work is a Task: retryTask marks it RENDERING, calls renderModelDestructive, emits the resulting model, and eventually marks the task COMPLETED. This is protocol production work, not evidence of a client fiber tag.

By contrast, the shown reconciler taxonomy names the kinds it recognizes while inspecting fibers, including ClassComponent, FunctionComponent, and several host kinds. The server renderer can still render function components through renderWithHooks, and its Fizz implementation separately checks class-component conventions, but those facts do not establish a ServerComponent reconciler tag.

The practical distinction is therefore boundary-based: a Server Component runs in the server Flight renderer and contributes a serializable model; host and class components are categories the reconciler uses when it builds or interprets a fiber tree. The client receives the resulting model and references, then initializes values and lets the normal client rendering path consume them.

Sources: packages/react-server/src/ReactFlightServer.js:6307-6439, packages/react-reconciler/src/getComponentNameFromFiber.js:19-50, packages/react-server/src/ReactFizzServer.js:2650-2676, packages/react-server/src/ReactFizzClassComponent.js:432-451, packages/react-client/src/ReactFlightClient.js:5650-5656

How it connects

The bundler-specific client adapters connect browser or Node streams to the shared Flight client functions createResponse, getRoot, processBinaryChunk, processStringChunk, and close. The Parcel fixture demonstrates the intended hand-off: it creates the initial root from a readable stream embedded in HTML, while the Flight payload itself remains a separate streamed model.

For bundler and manifest details, continue with Bundler Integrations for Server Components. For the HTML renderer that surrounds or embeds streamed content, see Server Rendering (Fizz). For the reconciler’s fiber categories and work loop, see Fiber Architecture and Render Phase.

Sources: packages/react-server-dom-webpack/src/client/ReactFlightDOMClientBrowser.js:21-30, fixtures/flight-parcel/src/client.tsx:11-20

Key takeaways

  • Flight sends framed, ID-addressed rows rather than plain HTML.
  • The client stores rows as chunks, parses models, revives references, and wakes dependent values.
  • $ and $L references let models point to separately streamed or lazy data.
  • Server Components are server-side Flight work, not a shown reconciler work-tag category.
  • Errors, binary data, text, cycles, and partial-stream closure are protocol cases handled by dedicated chunk states.

Want this for your repos?

Try Angada AI Wiki