Ya know, as a hobbyist programmer, I don't even know what problems some features solve but you explained it very nicely. Thank you, that's a really cool new feature.
This feature seems useful for a Navbar that shows the currently logged-in user (fetched server-side). Because that used to disable static caching for pretty much the whole app.
Hi lee rob, thanks for the update. Just wondering, what's the impact of SEO for content under suspense block? Traditionally, anything under suspense is considered client side, and it's not good for SEO. and hiding reviews under suspense is not good because of json schema thats tied to the reviews. Looking forward to hear your thought on this.
Google renders your page and looks at the DOM rather than caring at all how you deliver it. What's good for SEO is that PPR provides for very stable response times since the initial response is static and respectively the crawlers feel empowered to crawl your site very quickly.
True that Google bot also crawls while running JS, but what about all other seo bots, like bing, yahoo, etc. Its a fact that even though googlebot can execute js, you really want your SEO meat rendered on the server. In terms of perf, it helps SEO but not as much as other signals like metadata, content, etc rendered during SSR
as Google always mentions SEO is about "customer satisfaction and not regulations". Fast rendering means your visitors will likely stay and interact more, and which should impact your websites' rank the most; according to legends...
Not sure I understand. Wasn't it already possible to stream in other parts of the page that were slower by wrapping them in Suspense? How's this different? I understand that currently using suspense will make the whole route dynamic, but does it matter if the route is anyway hitting the fetch cache?
Today, there is static and dynamic rendering. There is also cached and uncached data. You can have dynamic rendering with all cached data, yet still reading dynamic parts like cookies and headers, today. However, this requires likely using the edge runtime (missing compatibility with Node.js ecosystem) and worse DX. Plus, you don't have consistent TTFB from serving a static file. PPR is cheaper and better DX.
This PR isn't done yet, but it's a good example of the before and after scenario I'm discussing in a real world use case. github.com/vercel/commerce/pull/1236
@@leerob thanks that makes things clearer. We're using dynamic rendering with all cached data and are quite happy with TTFB since it's just reading files from cache. I wonder if the performance is really that worst compared to static rendering (after all you still have to read and serve the html file with static). I guess rendering the React tree at every request can be slow, just curious if it's really that much slower? Can you expand on the edge part? Hitting fetch-cache is Node.js compatible for us and works great.
Question: In a dynamically rendered route, React streaming and suspense boundaries are already working in next.js. I.e. it starts sending chunks it has rendered once ready, defined by suspense boundaries. How is this (Partial Pretendering) different from this? Does it have to do with the fact that the suspense boundary now makes it possible for whatever was above the suspense boundary to be statically rendered? So, with PPR, it's no longer a fact that the entire route is dynamically rendered when using dynamic functions (headers, cookies, etc)?
Yo, Lee, what is the current talk about state-management though? With nextJS moving so fast, and with next-redux-wrapper basically dead in the water now unfortunately -- what is the model for server-client state-management? Because top-down state-management with hydration was already difficult in Next12, what are we suppose to do now?
What model do you expect? You don't need any wrapper, so initialize redux store exclusively on client. Redux can only interact with components through stateful hooks, so can't be used in server components anyway.
@@ra2enjoyer708 Do you have experience with next-redux-wrapper or redux-cookie-wrapper or the likes? I fully expect a unified solution to state management across the vertical stack of course. The same tool and technique on server and client.
@@MrNovado You don't need any of the wrappers, cookies and other browser storage interfaces can be accessed from async thunks. Also there won't be a "unified solution" because server and client work in different contexts and deal with barely intersecting sets of problems.
@@ra2enjoyer708 So you don't have experience with next-redux-wrapper? Why pitch in then? You either do not know what you talking about, or gatekeeping. With next-redux-wrapper it was already possible to achieve vertical state management in next12 (granted, to a variable degree of success). Me, my colleagues, and possibly the people liking the thread, have a clear-cut issue need solving. You either a part of a solution, or a part of a problem. No offence.
@@MrNovadoWhat the other user means is there is completly diference in the runtime of server and client components that make imposible a solution that works in both. This is not a lack of implementation, is part of the nature of this components. Server components run in server and don't have access to browser apis, while clients work on browser. Traditional state management require to be run on client, so they won't be available on server components. In Next 13 o 14, you can use state management and load only on the client components you require (done that with zustand).
I cannot wait until this is stable because I just migrated my entire blog over to the app router searching for a solution to have a dynamic view counter with a static blog page!
I'm not expert, but I think the way of doing that atm is to have a static page with a client component that fetches data from an API. It's not as nice, but it seems possible to do.
Important question: Next.js is supposed to know when a component is dynamic when it accesses an API or dynamic content as parameters to work correctly, if so how would it work with internationalization? Because it is necessary to access the “locale” or “lang” parameter in practically all content and therefore you would have to wait for this parameter. In that case I would mark it as dynamic and the partial prerender would not work because it would have to wait.
This sounds like the standard “render as you fetch” technique that Facebook has been using for years with relay and graphql. Relay is more difficult to learn. But, is a very elegant solution, once you get the hang of it.
For the "Recommended Products for You" section in the first example, say that was paginated, and clicking a left or right arrow would show 4 new products that are dynamic content. How do you re-trigger the suspense to show the loading fallback? I have only been able to get this to work on initial page load. Subsequent "calls" show the stale UI for x seconds while the request is running, then suddenly show the new content.
Hi Rob. Thank you for this video. I don't get why fetching the view count would make the whole route dynamic, as fas as I can see your are not using cookies or headers. You did mention "compute". I suspect this is the reason. What exactly do you mean by "compute"?
I have out of context question 😅 How to display more informations in error.tsx than just a simple message? I'd like to show i.e. title, description and cause. Is it possible?
Sir please,reply on when we use next js as frontend and node js as backend end how we can manage our middleware code for protecting routes because I send token in response of login api and i got it in client components and middleware run on server how I can pass token to server please explain this topic
Will there be option to use old value instead of loading state? On example of your blog, it could instantly show old number of views and update to actual number when fetched it
@@aniket-kulkarni if it works with 'next start' as Lee said it should also work with standalone. 'next start' and standalone mode are basically the same thing, In standalone mode the entire application is packaged as a standalone entity (no need to install next pkg to be able to run the app only nodejs should be installed)
Are there going to be any news on @next/mdx soon? Does next/mdx work with server components? Would love to move away from mdx-bundler and use your rust based compiler. I would love to see the tutorial on that on your website to be more in depth.
Speaking of the last example, if you wanted to revalidate the views count every minute, instead of fetching it on every visit with noStore(), how can you do that? I assume that if, instead of db read, you had a fetch there, you could set the revalidate on the fetch and it would work? How to do that with a db read? Put the db read on an API route, fetch the route and revalidate the fetch then?
If you're using fetch, then yeah, can pass revalidate as an option. If you doing a db read directly, you can use the cache function I was previously using in this video. nextjs.org/docs/app/api-reference/functions/unstable_cache
Sorry for the dumb question, but does the async call needs to be inside the dynamic component? Or can we do this outside with a prop to feed those components?
well it's up to you. you can encapsulate specific logic into their own server components and combine those into pages. that would also allow you to wrap some dynamic content with suspense. but if you have all the dynamic stuff on the top level, you won't be able to get any static out of it
I've tested the template on my local machine. I've added a console.log to layout.tsx and page.tsx. Then I build the site and have run start. On each page refresh I see both log messages on the server console. What I'm missing? Since both are statically rendered I wouldn't expect the console message to see.
Am I somehow able to access search parameters from a component (server rendered), which is within a Suspense boundary? Currently I have to use searchParams on page level, which makes the full page dynamic.
The page only becomes dynamic when you read the searchParams. So you can use searchParams on the page, pass it to a child component that's wrapped with Suspense, and the shell would still be static.
hi mr lee hope you're doing well , i have a question , lets suppose i'am building a nextjs app using nextjs 13 , and the version 14 comes out , can i benefit from the new updates like that one in my project that i'am building with 13 ? is it just an update ?
Ya know, as a hobbyist programmer, I don't even know what problems some features solve but you explained it very nicely. Thank you, that's a really cool new feature.
This feature seems useful for a Navbar that shows the currently logged-in user (fetched server-side). Because that used to disable static caching for pretty much the whole app.
The lighthouse score on that site 🤯
Really like this new feature. It feels really similar to the "Islands" Architecture pioneered by Astro.
Hi lee rob, thanks for the update. Just wondering, what's the impact of SEO for content under suspense block? Traditionally, anything under suspense is considered client side, and it's not good for SEO. and hiding reviews under suspense is not good because of json schema thats tied to the reviews. Looking forward to hear your thought on this.
Both can be under Suspense SSR & CSR if I understand correctly.
Google renders your page and looks at the DOM rather than caring at all how you deliver it.
What's good for SEO is that PPR provides for very stable response times since the initial response is static and respectively the crawlers feel empowered to crawl your site very quickly.
True that Google bot also crawls while running JS, but what about all other seo bots, like bing, yahoo, etc. Its a fact that even though googlebot can execute js, you really want your SEO meat rendered on the server. In terms of perf, it helps SEO but not as much as other signals like metadata, content, etc rendered during SSR
as Google always mentions SEO is about "customer satisfaction and not regulations". Fast rendering means your visitors will likely stay and interact more, and which should impact your websites' rank the most; according to legends...
4:50 Streaming SSR with Suspense wouldn’t block for the slowest data fetch. It builds on traditional SSR and is a simpler model than PPR.
Not sure I understand. Wasn't it already possible to stream in other parts of the page that were slower by wrapping them in Suspense? How's this different? I understand that currently using suspense will make the whole route dynamic, but does it matter if the route is anyway hitting the fetch cache?
Today, there is static and dynamic rendering. There is also cached and uncached data. You can have dynamic rendering with all cached data, yet still reading dynamic parts like cookies and headers, today. However, this requires likely using the edge runtime (missing compatibility with Node.js ecosystem) and worse DX. Plus, you don't have consistent TTFB from serving a static file. PPR is cheaper and better DX.
This PR isn't done yet, but it's a good example of the before and after scenario I'm discussing in a real world use case. github.com/vercel/commerce/pull/1236
@@leerob thanks that makes things clearer. We're using dynamic rendering with all cached data and are quite happy with TTFB since it's just reading files from cache. I wonder if the performance is really that worst compared to static rendering (after all you still have to read and serve the html file with static). I guess rendering the React tree at every request can be slow, just curious if it's really that much slower?
Can you expand on the edge part? Hitting fetch-cache is Node.js compatible for us and works great.
May be he meant dynamic rendering nearby users at edge locations to reduce latency. @leerob can you please confirm?
Great job folks ! 🎉
Question: In a dynamically rendered route, React streaming and suspense boundaries are already working in next.js. I.e. it starts sending chunks it has rendered once ready, defined by suspense boundaries. How is this (Partial Pretendering) different from this? Does it have to do with the fact that the suspense boundary now makes it possible for whatever was above the suspense boundary to be statically rendered? So, with PPR, it's no longer a fact that the entire route is dynamically rendered when using dynamic functions (headers, cookies, etc)?
You are correct. Now, the parts above the suspense boundaries, and their fallbacks, can be statically generated (and use ISR).
wow! now im clear. @@leerob
Yo, Lee, what is the current talk about state-management though? With nextJS moving so fast, and with next-redux-wrapper basically dead in the water now unfortunately -- what is the model for server-client state-management? Because top-down state-management with hydration was already difficult in Next12, what are we suppose to do now?
What model do you expect? You don't need any wrapper, so initialize redux store exclusively on client. Redux can only interact with components through stateful hooks, so can't be used in server components anyway.
@@ra2enjoyer708 Do you have experience with next-redux-wrapper or redux-cookie-wrapper or the likes? I fully expect a unified solution to state management across the vertical stack of course. The same tool and technique on server and client.
@@MrNovado You don't need any of the wrappers, cookies and other browser storage interfaces can be accessed from async thunks. Also there won't be a "unified solution" because server and client work in different contexts and deal with barely intersecting sets of problems.
@@ra2enjoyer708 So you don't have experience with next-redux-wrapper? Why pitch in then? You either do not know what you talking about, or gatekeeping. With next-redux-wrapper it was already possible to achieve vertical state management in next12 (granted, to a variable degree of success). Me, my colleagues, and possibly the people liking the thread, have a clear-cut issue need solving. You either a part of a solution, or a part of a problem. No offence.
@@MrNovadoWhat the other user means is there is completly diference in the runtime of server and client components that make imposible a solution that works in both. This is not a lack of implementation, is part of the nature of this components. Server components run in server and don't have access to browser apis, while clients work on browser. Traditional state management require to be run on client, so they won't be available on server components. In Next 13 o 14, you can use state management and load only on the client components you require (done that with zustand).
Perfectly explained!
was looking for your channel but it found me instead, Subscribed!
I cannot wait until this is stable because I just migrated my entire blog over to the app router searching for a solution to have a dynamic view counter with a static blog page!
I'm not expert, but I think the way of doing that atm is to have a static page with a client component that fetches data from an API. It's not as nice, but it seems possible to do.
Important question: Next.js is supposed to know when a component is dynamic when it accesses an API or dynamic content as parameters to work correctly, if so how would it work with internationalization? Because it is necessary to access the “locale” or “lang” parameter in practically all content and therefore you would have to wait for this parameter. In that case I would mark it as dynamic and the partial prerender would not work because it would have to wait.
This sounds like the standard “render as you fetch” technique that Facebook has been using for years with relay and graphql. Relay is more difficult to learn. But, is a very elegant solution, once you get the hang of it.
For the "Recommended Products for You" section in the first example, say that was paginated, and clicking a left or right arrow would show 4 new products that are dynamic content. How do you re-trigger the suspense to show the loading fallback? I have only been able to get this to work on initial page load. Subsequent "calls" show the stale UI for x seconds while the request is running, then suddenly show the new content.
It seems that this works "automatically" without having to do anything special (besides setting suspense boundaries). Is that correct?
except Vercel where else can I use PPR? Cloudflare perhaps?
Does PPR only work for the app router?
What is The difference between loading.tsx and doing this?
And if i decide to use pppr (suspense) - should i Then Stop using loading.tsx?
`loading` just makes a Suspense boundary for you automatically!
Hi Rob. Thank you for this video.
I don't get why fetching the view count would make the whole route dynamic, as fas as I can see your are not using cookies or headers.
You did mention "compute". I suspect this is the reason. What exactly do you mean by "compute"?
I have out of context question 😅 How to display more informations in error.tsx than just a simple message? I'd like to show i.e. title, description and cause. Is it possible?
The demo loads all at the same time for me, albeit with a 2000ms delay ?
Sir please,reply on when we use next js as frontend and node js as backend end how we can manage our middleware code for protecting routes because I send token in response of login api and i got it in client components and middleware run on server how I can pass token to server please explain this topic
Will there be option to use old value instead of loading state? On example of your blog, it could instantly show old number of views and update to actual number when fetched it
I'm building a big Ecom store today which will probably be done in like 6 months. Do you expect to have this tech stable by then?
Hey Lee, Cool stuff! I wonder Partial Prerendering can be implemented outside of Vercel infrastructure e.g. using docker and running on kubernetes.
Thats the important question
Yeah, it works when you use `next start`! What Vercel is providing on top is the multi-region, global CDN.
@@leerob thank you for the confirmation!
Hi Lee. Does it mean that it doesn't work in standalone mode?
@@aniket-kulkarni if it works with 'next start' as Lee said it should also work with standalone.
'next start' and standalone mode are basically the same thing, In standalone mode the entire application is packaged as a standalone entity (no need to install next pkg to be able to run the app only nodejs should be installed)
Are there going to be any news on @next/mdx soon? Does next/mdx work with server components? Would love to move away from mdx-bundler and use your rust based compiler. I would love to see the tutorial on that on your website to be more in depth.
Yes, @next/mdx works with App Router. You can also use this: github.com/hashicorp/next-mdx-remote
Speaking of the last example, if you wanted to revalidate the views count every minute, instead of fetching it on every visit with noStore(), how can you do that? I assume that if, instead of db read, you had a fetch there, you could set the revalidate on the fetch and it would work? How to do that with a db read? Put the db read on an API route, fetch the route and revalidate the fetch then?
If you're using fetch, then yeah, can pass revalidate as an option. If you doing a db read directly, you can use the cache function I was previously using in this video.
nextjs.org/docs/app/api-reference/functions/unstable_cache
i tried to use server actions with parallel routes but it doesn't work. it gets stuck !!
Awesome
Does it works on prod only env (next start) or on dev server too?
I want to know the difference between PPR and dynamic(() => import(...), {loading})
Sorry for the dumb question, but does the async call needs to be inside the dynamic component? Or can we do this outside with a prop to feed those components?
well it's up to you. you can encapsulate specific logic into their own server components and combine those into pages. that would also allow you to wrap some dynamic content with suspense. but if you have all the dynamic stuff on the top level, you won't be able to get any static out of it
Hey Lee, is your personal blog website is open-source? if yes can you bring us the link so we can follow the news you are using there?
I've tested the template on my local machine. I've added a console.log to layout.tsx and page.tsx. Then I build the site and have run start. On each page refresh I see both log messages on the server console. What I'm missing? Since both are statically rendered I wouldn't expect the console message to see.
Did you figure out why, I did the test as you and got confused as well.
Am I somehow able to access search parameters from a component (server rendered), which is within a Suspense boundary? Currently I have to use searchParams on page level, which makes the full page dynamic.
Yea just forward the url in the headers from your middleware right?
The page only becomes dynamic when you read the searchParams. So you can use searchParams on the page, pass it to a child component that's wrapped with Suspense, and the shell would still be static.
@@leerob Interesting. This is already the case? I did not know that.
But can you incrementally regenerate your partially pre-rendered shell?
yes! Same as ISR
Lee is The Truth
What is ssg then
Need a client side state management along with server side
lee is sounding a bit congested
Haha I noticed this too, I'm a little congested today tbh
hi mr lee hope you're doing well , i have a question , lets suppose i'am building a nextjs app using nextjs 13 , and the version 14 comes out , can i benefit from the new updates like that one in my project that i'am building with 13 ? is it just an update ?
There's no new APIs in Next.js 14 and only a handful of small breaking changes. Should be a very simple upgrade, I'd recommend.
TIL about noStore() (unstable_noStore())