Next.js Discord

Discord Forum

Is streaming only for dynamically rendered content?

Answered
Oriental posted this in #help-forum
Open in Discord
OrientalOP
I can't find an exact answer on this in the documentation, maybe I have not looked well enough. My question: is streaming only applied to routes which are dynamically rendered and not statically rendered routes?

From my understanding, statically rendered routes are built entirely on the server and cached. So, this should mean I don't have to worry about network waterfalls when a route is statically rendered and streaming individual components, but I am not sure.

I guess I should've specified that I am asking for Next 14.
Answered by LuisLl
From my understanding, statically rendered routes are built entirely on the server and cached. So, this should mean I don't have to worry about network waterfalls when a route is statically rendered and streaming individual components, but I am not sure.
Correct, Static routes at generated at build time and always served from the cache when they are requested either by 1 or 1000 users.
So yes, there's no point on streaming static routes since they're pre-rendered at build time.

That said, here you have to consider multiple scenarios since a route is not always fully static or fully dynamic:
1. If the route is 100% static, meaning it does not contain any async operation going on then the whole route component will get statically generated.
2. If you want the route to be static but it needs to fetch it's own data, then this data will be fetch on build time and will never change since you're gonna be serving the cached results of that first render. I believe this is the default in Next.js 14, but you can enforce this with export const dynamic = "force-static"
3. (This might be the one that interests you) When you want a static route and you also want to stream dynamic segments or components, the only way is to have these dynamic segments wrapped in <Suspense> so the static output generated at build time contains the fallbacks in place of the dynamic slots. And you might want to turn on Partial Prerendering to let Next.js figure out which parts of your route need to be dynamic so it can keep static the rest that doesn't need it.
View full answer

19 Replies

From my understanding, statically rendered routes are built entirely on the server and cached. So, this should mean I don't have to worry about network waterfalls when a route is statically rendered and streaming individual components, but I am not sure.
Correct, Static routes at generated at build time and always served from the cache when they are requested either by 1 or 1000 users.
So yes, there's no point on streaming static routes since they're pre-rendered at build time.

That said, here you have to consider multiple scenarios since a route is not always fully static or fully dynamic:
1. If the route is 100% static, meaning it does not contain any async operation going on then the whole route component will get statically generated.
2. If you want the route to be static but it needs to fetch it's own data, then this data will be fetch on build time and will never change since you're gonna be serving the cached results of that first render. I believe this is the default in Next.js 14, but you can enforce this with export const dynamic = "force-static"
3. (This might be the one that interests you) When you want a static route and you also want to stream dynamic segments or components, the only way is to have these dynamic segments wrapped in <Suspense> so the static output generated at build time contains the fallbacks in place of the dynamic slots. And you might want to turn on Partial Prerendering to let Next.js figure out which parts of your route need to be dynamic so it can keep static the rest that doesn't need it.
Answer
If I'm not mistaken, the default behavior in Next.js 14 without PPR enabled (Partial Pre-rendering) is either to make the route static or to make it dynamic, only one of those two can be. To allow having both static and dynamic segments per route level you need to enable PPR and place <Suspense> boundaries granularly, especially for components that depend on request-time data.
OrientalOP
Yeah that's my understanding
Are you having any specific issues with how the default behavior is supposed to behave?
OrientalOP
And here are the ways that a route becomes dynamically rendered.
I don't think it has anything to do with async/await if I'm not mistaken
@LuisLl Are you having any specific issues with how the default behavior is supposed to behave?
OrientalOP
No, this was purely a trying to understand the idea question.
Not yet in Next.14 but it does in Next.15
OrientalOP
In 15 async await will cause a route to become dynamically rendered?
All Dynamic APIs and Dynamic Functions are now promises that need to be awaited, this to tell Next.js which components or routes need to be dynamic.
OrientalOP
Ok well I'll worry about that whenever I decide to use 15 lol
@Oriental In 15 async await will cause a route to become dynamically rendered?
You can force it to be static with const dynamic = "force-static" and if you have PPR enabled Next.js will decide if the page can be pre-rendered if it does not have any async or dynamic API
So basiaclly Next v15 made it easier to detect which parts are dynamic and which can be kept static
@Oriental No, this was purely a trying to understand the idea question.
Okay, good. Let me know if you need more help and I'll see if i can help
OrientalOP
Yeah I wasn't having any particular issue, just wanted to make sure I wasn't blocking the UI from being loaded on my statically built routes. But after chatting right now it should be a non issue since the static routes are rendered at build time so streaming doesn't make sense in that context
You can try and build your app to have the summary of the pages and the rendering strategy each one has. If you believe some route should be static because 99% of it indicates that and in the summary it appears as dynamic this might be caused by a deep component that's making use of dynamic apis
So it can help you debug easier.
@Oriental make sure to mark the solution to the original question! :p