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.
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.
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.
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...
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).
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)?
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.
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"?
@@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)
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
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.
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
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
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.
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?
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
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 ?
The nice part is that you don't really need to understand this deeply, the framework is just trying to help you do the right things. But we'll continue to add more docs and such as it becomes stable!
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.
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.
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.
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...
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).
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
Great job folks ! 🎉
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?
Perfectly explained!
was looking for your channel but it found me instead, Subscribed!
It seems that this works "automatically" without having to do anything special (besides setting suspense boundaries). Is that correct?
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.
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"?
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)
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
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!
Awesome
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.
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
Lee is The Truth
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
I want to know the difference between PPR and dynamic(() => import(...), {loading})
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.
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?
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?
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
The demo loads all at the same time for me, albeit with a 2000ms delay ?
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?
Does PPR only work for the app router?
Does it works on prod only env (next start) or on dev server too?
Need a client side state management along with server side
i tried to use server actions with parallel routes but it doesn't work. it gets stuck !!
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
What is ssg then
TIL about noStore() (unstable_noStore())
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.
I hope I'm not the only one who's confused af :))
The nice part is that you don't really need to understand this deeply, the framework is just trying to help you do the right things. But we'll continue to add more docs and such as it becomes stable!