cloudflare / cloudflare/vinext
App Router RSC wire format: unify FlightData/FlightRouterState/CacheNodeSeedData into a single TransportData tree
- Dominant language
- TypeScript
- Stars
- 8.8k
- Forks
- 406
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 120
Description
## Upstream change
Next.js replaced its RSC response transport format. Previously a server response was two parallel, isomorphic trees walked in lockstep: `FlightRouterState` (route structure) and `CacheNodeSeedData` (rendered output), encoded as `FlightDataPath` entries (repeating `[segment, parallelRouteKey]` prefixes terminated by a positional data tuple). These are unified into a single `TransportData` tree where each node carries both its segment identity, prefetch hints, and (optionally) its render output. The same shape is used whether the whole page is rendered or some segments are omitted (absence = "nothing here / fetch lazily").
Landed across a 3-PR stack:
- Unify RouteTree and CacheNodeSeedData on the client (#96406) — https://github.com/vercel/next.js/commit/4ce4c519027c307709406249448af525a9610a8e
- Unify full/partial navigation response types, introduce `TransportData` via a temporary adapter (#96439) — https://github.com/vercel/next.js/commit/c37b736862d0ad258809f986ea8e34da843d57c8
- Refactor server from `CacheNodeSeedData` -> `TransportData`, delete the adapter (#96679) — https://github.com/vercel/next.js/commit/c713d48763dd9c9d34fe2b99829cf3f1ada78dc5
## What changed
- New transport types live in `packages/next/src/shared/lib/rsc-transport.ts` (`TransportSegment`, `TransportDynamicSegment`, `TransportSegmentData`, `TransportData`). Node fields are terse single letters (`n`/`t`/`k`/`s` for dynamic segments; `r`/`p`/`v` for render output).
- Server: `createComponentTree` now returns the transport tree directly; `createFlightRouterStateFromLoaderTree` -> `createTransportTreeFromLoaderTree`; `walkTreeWithFlightRouterState` emits transport nodes with "skipped" placeholders above the emitted node; the `generateDynamicRSCPayload` root-segment slice hack is deleted. `FlightData`/`FlightDataPath`/`FlightDataSegment` types removed. `CacheNodeSeedData` deleted from the codebase.
- Client decodes `TransportData` into its existing richer `RouteTree`/`CacheNode` at the network boundary and never stores transport types. `FlightRouterState` survives only for issuing requests (`Next-Router-State-Tree`) and browser history state.
- Non-PPR prefetch that stops at a loading boundary emits the subtree below the cut as structure-only nodes (no render output).
- Prefetch hints computed once via `computeSegmentPrefetchHints`, shared between the two producers.
- Also deletes the dead `overriddenSegment` / `canSegmentBeOverridden` mechanism.
## Why it matters for vinext
vinext reimplements the App Router RSC entry, the RSC stream/payload serialization, and client-side navigation. The RSC response payload is the contract between vinext's server-rendered RSC stream and its client router. If vinext currently produces/consumes the old `FlightData` + `CacheNodeSeedData` + `FlightRouterState` shape (or relies on those trees being isomorphic), it will drift from Next.js clients/tooling and any code that expects the unified single-tree format. We should track whether vinext's payload format needs to migrate to `TransportData`, and audit our navigation/prefetch decode path against the new "absence = fetch lazily" convention and the structure-only-below-loading-boundary behavior.
## Action
- Audit vinext's RSC payload producer (App Router RSC entry) and client navigation decode path for the old FlightData/CacheNodeSeedData shape.
- Decide whether to adopt the unified `TransportData` tree for wire compatibility, or document a deliberate divergence.
- Verify non-PPR loading-boundary prefetch emits structure-only subtrees, and that prefetch hints are computed consistently between full-render and route-tree-only producers.
## References
- https://github.com/vercel/next.js/commit/4ce4c519027c307709406249448af525a9610a8e (#96406)
- https://github.com/vercel/next.js/commit/c37b736862d0ad258809f986ea8e34da843d57c8 (#96439)
- https://github.com/vercel/next.js/commit/c713d48763dd9c9d34fe2b99829cf3f1ada78dc5 (#96679)
Contributor guide
Research direction
Start with the App Router RSC entry and the client navigation decode path, then compare their payload handling with packages/next/src/shared/lib/rsc-transport.ts and the referenced upstream commits. Determine whether vinext should adopt TransportData or document a deliberate divergence; verify structure-only subtrees below loading boundaries and consistent prefetch hints.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- next.js, react, typescript
- Domain
- api, backend-api-design, frontend
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100