rsnext/test/e2e/app-dir/ppr-full/components
Josh Story ff7c5c2ba3
Support resuming a complete HTML prerender that has dynamic flight data (#60865)
followup to: https://github.com/vercel/next.js/pull/60645

### Background

When prerendering the determination of whether a prerender is fully
static or partially static should not be directly related to whether
there is a postponed state or not. When rendering RSC it is possible to
postpone because a dynamic API was used but then on the client (SSR) the
postpone is never encountered. This can happen when a server component
is passed to a client component and the client component conditionally
renders the server component.

Today if this happens the entire output would be considered static when
in fact the flight data encoded into the page and used for bootstrapping
the client router contains dynamic holes. Today this is blocked by an
error that incorrectly assumes that this case means the user caught the
postpone in the client layer but as shown above this may not be the
case.

### Implementation

A more capable model is to think of the outcome of a prerender as having
3 possible states
1. Dynamic HTML: The HTML produces by the prerender has dynamic holes.
we save the static prelude but expect to resume the render later to
complete the HTML. This means we will resume the RSC part of the render
as well
2. Dynamic Data: The HTML is completely static but the RSC data encoded
into the page is dynamic. We don't want to resume the render but we do
need to produce new inlined RSC data during a Request.
3. Static: The HTML is completely static and so is the RSC data encoded
into the page. We save the entire HTML output and there will be no
dynamic continuation when this route is visited.

Really 1 & 3 are the same as today (Partially static & Fully Static
respectively) but case 2 which today errors in a confusing way is now
supported.

In addition implementing the Dynamic Data case the old warning about
catching postpones is removed. The reason we don't want this is that
catching postpones is potentially a valid way to do optimistic UI. We
probably want a first-party API for it at some point (and maybe we'll
add the warning back in once we do) but imagine you do something dynamic
like look up a user but during prerender you want to render as if the
user is logged out. you could call `getUser()` in a try catch and render
fallback UI if it throws. In this case we'd detect a dynamic API was
used but we wouldn't have a corresponding postpone state which would put
us in the Dynamic Data case (2).

Another item to note is that we can produce a fully static result even
if there is a postponed state because users may call postpone themselves
even if they are not calling dynamic APIs like headers or cookies. When
this happens we don't want to statically capture a page with postponed
boundaries in it. Instead we immediately resume the render and abort it
with a postponed abort signal. This will cause the boundaries to
immediately enter client render mode which should speed up recovery on
the client.

#### Technical Note

Another note about the implementation is that you'll see that regardless
of which case we are in, if there is a postponed state but we consider
the page to be Dynamic Data meaning we want to serialize all the HTML
and NOT do a resume in the dynamic continuation then we immediately
resume the render with and already aborted AbortSignal. The purpose here
is to mark any boundaries which have dynamic holes as being
client-rendered.

As a general rule if the render produces a postponed state we must do
one of the following
1. save the postponed state and ensure there is a dynamic continuation
that calls resume
2. immediately resume the render and save the concatenated output and
ensure the dynamic continuation does NOT call resume.

or said another way, every postponed state must be resumed (even if it
didn't come from Next's dynamic APIs)

#### Perf considerations

This PR modifies a few key areas to improve perf.

Reduces quantity of *Stream instances where possible as these add
significant overhead
Reduces extra closures to lower allocations and keep functions in
monomorphic form where possible


Closes NEXT-2164
2024-02-12 15:59:13 -08:00
..
dynamic.jsx Partial Pre Rendering Headers (#59447) 2023-12-14 13:14:06 -07:00
layout.jsx Partial Pre Rendering Headers (#59447) 2023-12-14 13:14:06 -07:00
links.jsx Navigation Signals in PPR (#60450) 2024-02-06 12:25:50 -07:00
optimistic.jsx Support resuming a complete HTML prerender that has dynamic flight data (#60865) 2024-02-12 15:59:13 -08:00
server-html.jsx Support resuming a complete HTML prerender that has dynamic flight data (#60865) 2024-02-12 15:59:13 -08:00