Suspense Boundary inside `layout.tsx` with `ppr` and `dynamicIO` enabled

Hi guys, I was watching theo's video on why is next.js so slow and my mental model for DynamicIO + PPR went downhill after the part he adds a Suspense wrapping children in the layout and that doesn't work. I've tried to follow the explanation but I didn't really get it why it didn't work... I thought the compiler would pre-render everything until the first async component for that route (including layouts) and put that in the static bundle for the route. Can anyone please explain what I'm missing here?
Theo - t3․gg
YouTube
Why is Next.js so slow??
A lot of server component apps have been rough, but I don't think that's NextJS' fault. There's a lot to talk about with how this new model actually works... Thank you Sevalla for sponsoring! Check them out at: https://soydev.link/sevalla Want to see how fast NextJS can be? Check out: https://soydev.link/chat SOURCES https://github.com/t3dotg...
Solution:
I consider layouts to generally be static in the sense that they don’t re-render once delivered. Their children update, but they don’t normally. https://nextjs.org/docs/app/getting-started/layouts-and-pages Suspense doesn’t work after first render because on first render, the generated layout sees that the child is streaming in, and therefore shows the Suspense boundary fallback. When we return to or move to a dynamic component after this, it’s slotting in the child but doesn’t re-run the suspense because the layout doesn’t re-render, preventing the suspense from running. Suspense can only run when a component is dynamically mounting/rendering or slotting in, and since the layout component doesn’t do that on change for child components, it can’t properly trigger the suspense within the layout component. The suspense also wouldn’t run if we refreshed or started on the second page or static page, then clicked on first page for the same reason. The suspense being in layout isn’t “wrong” (it works on page load if you’re on the dynamic component), but it just isn’t useful because layout doesn’t re-render at all. Suspense is better off being placed in a component that consistently rerenders with the dynamic component we’re trying to account for....
Getting Started: Layouts and Pages | Next.js
Create your first pages and layouts, and link between them.
Jump to solution
3 Replies
Solution
The Guy
The Guy5d ago
I consider layouts to generally be static in the sense that they don’t re-render once delivered. Their children update, but they don’t normally. https://nextjs.org/docs/app/getting-started/layouts-and-pages Suspense doesn’t work after first render because on first render, the generated layout sees that the child is streaming in, and therefore shows the Suspense boundary fallback. When we return to or move to a dynamic component after this, it’s slotting in the child but doesn’t re-run the suspense because the layout doesn’t re-render, preventing the suspense from running. Suspense can only run when a component is dynamically mounting/rendering or slotting in, and since the layout component doesn’t do that on change for child components, it can’t properly trigger the suspense within the layout component. The suspense also wouldn’t run if we refreshed or started on the second page or static page, then clicked on first page for the same reason. The suspense being in layout isn’t “wrong” (it works on page load if you’re on the dynamic component), but it just isn’t useful because layout doesn’t re-render at all. Suspense is better off being placed in a component that consistently rerenders with the dynamic component we’re trying to account for.
Getting Started: Layouts and Pages | Next.js
Create your first pages and layouts, and link between them.
The Guy
The Guy5d ago
Specifically regarding re-rendering: “A layout is UI that is shared between multiple pages. On navigation, layouts preserve state, remain interactive, and do not rerender.”
Filipi
FilipiOP3d ago
Thanks for the detailed explanation. Layouts being "static" explains what I was missing!

Did you find this page helpful?