Open-Source Wikis

/

React

/

Packages

/

react-server-dom-* packages

facebook/react

react-server-dom-* packages

Active contributors: sebmarkbage, unstubbable, gnoff

Purpose

The react-server-dom-* packages are the bundler-specific clients and servers for React Server Components (RSC). All of them share the same Flight wire format (defined in react-server) but differ in how they interpret client references and server references — i.e. how they map Flight payload entries to the actual JS modules and how they package functions for round-tripping.

There are seven of them:

Package Purpose
react-server-dom-webpack webpack bindings (Node + Edge runtimes). The most-used in the ecosystem; what Next.js uses.
react-server-dom-parcel Parcel bindings.
react-server-dom-turbopack Turbopack bindings. Next.js's newer bundler.
react-server-dom-esm Pure-ESM bindings — the bundler is the browser/Node import resolver.
react-server-dom-unbundled Like esm but with no module resolution at all; the user provides client/server reference resolvers.
react-server-dom-fb Facebook-internal bundler (Metro / Wave).
react-flight-server-fb New as of #36309 — the Facebook-specific Flight server, separate from the client.

Plus react-markup, which renders an RSC tree to a string of markup rather than streaming it.

What's the same

Every package wraps react-server (for the writer) and react-client (for the reader) and exposes:

  • renderToPipeableStream(model, manifest, opts?) / renderToReadableStream(...) — Flight writer entry. Takes a React element (or a thenable for one) and a bundler manifest.
  • createFromFetch(promise, opts?) / createFromReadableStream(stream, opts?) / createFromNodeStream(...) — Flight reader entry. Returns a React element you can render.
  • decodeReply(body, manifest, opts?) / decodeReplyFromAsyncIterable(...) — Server Actions reply decoder.
  • decodeAction(body, manifest) / decodeFormState(action, formState, manifest) — bridge from a fetch response to a callable action.
  • registerServerReference(fn, id, exportName) / registerClientReference(...) — runtime APIs for marking modules as server- or client-only when the bundler can't.

The shared client runtime is in packages/react-client/src/ReactFlightClient.js (~3,000 lines).

What differs

The bundler-specific code lives in each package's src/:

  • <pkg>/src/ReactFlightDOMClient<Variant>.js — the user-facing reader.
  • <pkg>/src/ReactFlightDOMServer<Variant>.js — the user-facing writer.
  • <pkg>/src/ReactFlightServerConfig<Pkg>.js — pluggable config for the writer (how to resolve client references).
  • <pkg>/src/ReactFlightClientConfig<Pkg>.js — pluggable config for the reader (how to load a client reference).
  • <pkg>/src/loaders/ — bundler plugins (webpack loader, Parcel transformer, etc.).

Examples:

  • packages/react-server-dom-webpack/src/ReactFlightClientConfigBundlerWebpack.js — knows how to look up an entry in webpack's __webpack_require__ and friends.
  • packages/react-server-dom-parcel/src/ReactFlightClientConfigBundlerParcel.js — same idea, but for Parcel's runtime.
  • packages/react-server-dom-turbopack/src/loaders/RSDWClientLoader.js — Turbopack loader.

Server Actions

Server Actions are server functions you can call directly from the client. The flow:

sequenceDiagram
  participant Client as Client (browser)
  participant Bundler as Bundler runtime
  participant Server as RSC server

  Server->>Client: Flight payload row "F123" (server reference)
  Client->>Bundler: form action="$action123" or onClick={action}
  Client->>Server: POST /action123 (multipart with serialized args)
  Server->>Server: ReactFlightReplyServer decodes args
  Server->>Server: invoke the bound function
  Server->>Client: Flight stream (return value)
  Client->>Client: createFromReadableStream → React element / value

The encoder/decoder pair is intentionally symmetric. Each package supplies its own way of identifying a function (webpack chunk + export, parcel asset id, turbopack module name, etc.).

Directory layout (typical, using react-server-dom-webpack)

packages/react-server-dom-webpack/
├── package.json
├── client.js / client.browser.js / client.edge.js / client.node.js
├── server.js / server.browser.js / server.edge.js / server.node.js
├── server.unbundled.js
├── static.js / static.edge.js / static.node.js
├── node-loader.js / node-register.js
└── src/
    ├── ReactFlightDOMClient.js                    # createFromFetch / createFromReadableStream
    ├── ReactFlightDOMClientNode.js / Edge.js / Browser.js
    ├── ReactFlightDOMServer.js                    # renderToReadableStream / renderToPipeableStream
    ├── ReactFlightDOMServerNode.js / Edge.js
    ├── ReactFlightClientConfigBundlerWebpack.js   # how to resolve a client reference
    ├── ReactFlightServerConfigBundlerWebpack.js
    ├── ReactFlightClientConfig{Browser,Edge,Node}.js
    ├── ReactFlightServerConfig{Edge,Node}.js
    └── loaders/                                    # webpack loader + entry plugins

How to choose

If you are writing a framework, you pick the package that matches your bundler. If you are writing a bundler, you have two options:

  1. Implement webpack-compatible manifests (or parcel/turbopack-compatible). Use the matching react-server-dom-* package.
  2. Use react-server-dom-unbundled and supply your own loadClientReference / prepareDestinationForModule callbacks. This is what Vite's RSC plugin and several research bundlers do.
  • react-server — the shared writer/reader infrastructure.
  • features/server-components — the user-facing pipeline.
  • packages/react-client/src/ReactFlightClient.js — the bulk of the client decoder logic.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

react-server-dom-* packages – React wiki | Factory