На build Next рендерит route до <Suspense>, React postpone паузит на dynamic boundary, shell — static prelude, holes — где остановились. На request — один response: shell из cache, dynamic стримится в holes.
Разбор
Flow на request time — не два round-trip:
- Static shell (включая Suspense fallbacks) flushes из cache — отличный TTFB, без server render shell.
- Server resume postponed work, render dynamic components, stream в holes по тому же connection.
«Dynamic» component — как раньше: cookies(), headers(), searchParams, uncached fetch. Разница — containment: APIs делают dynamic только свой Suspense subtree, не весь route. Dynamic API вне boundary всё ещё отравляет shell — ошибка, которую PPR показывает явно.
Next 15: experimental — experimental.ppr, per-route export const experimental_ppr = true, canary line.
Итог
PPR = build-time shell + request-time stream в Suspense holes; boundary обязателен, иначе dynamic API отравит всю страницу.