App router static generation on the fly with the option to fetch some data on the client
Unanswered
Holland Lop posted this in #help-forum
Holland LopOP
Hey guys. For a new project we are planning on using the App router in the context of an e-commerce platform. Let me quickly try to sketch my issue.
We have a link with a CMS (storyblok in our case, very similar to contentful) with contains all the data we need to build are pages. I know we can pre-generate this page content using
Now comes the interesting part, the price is not the same for every visitor of that page, it also depends on the logged in user. Some logged in users get a discounted price so I should make some kind of price call on the client. This is really confusing me as the project lead just told me to go head an rendering these pages statically.
Anyone that has experienced these kind of requirements before that could possibly point me into the right direction? Is it a good idea to statically generate these pages at all?
We have a link with a CMS (storyblok in our case, very similar to contentful) with contains all the data we need to build are pages. I know we can pre-generate this page content using
generateStaticParams + use revalidate with some timing. The page content can contain a product carousel component, this component is just a list of cards with some product data inside: description, stock status, BUT also a price.Now comes the interesting part, the price is not the same for every visitor of that page, it also depends on the logged in user. Some logged in users get a discounted price so I should make some kind of price call on the client. This is really confusing me as the project lead just told me to go head an rendering these pages statically.
Anyone that has experienced these kind of requirements before that could possibly point me into the right direction? Is it a good idea to statically generate these pages at all?
22 Replies
PPR allows you to have dynamic components within static pages
it's an experimental feature but it covers exactly your use case
then, the alternative as you rightfully mentioned, is using a client componet specifically for this user-specific data
the client component will call a route handler to get the data and display them
that's slightly less efficient than PPR, but it has the advantage of not being experimental
I've written a whole course around both these patterns: https://www.newline.co/courses/blazing-fast-next.js-with-react-server-components
Holland LopOP
Is see PPR is experimental and I need something production ready I think
@Eric Burel If I would pick the other solution, using a client component. Does that just mean adding use client at the top and making the call at the client?
@Holland Lop <@769111741098622976> If I would pick the other solution, using a client component. Does that just mean adding use client at the top and making the call at the client?
yes I think you could fetch the price on client side while rendering the default price on the server or just render it on client side if the price doesn't need SEO like this
export default async function Page() {
const product = await getProduct()
return (
<div>
...
<Price defaultPrice={product.price} />
...
</div>
)
}
// price.tsx
'use client'
export default function Price(props) {
const [price, setPrice] = useState()
useEffect(() => {
// fetch price
}, [])
return (
<div>{price ?? props.defaultPrice}</div>
)
}Holland LopOP
@Ray Thx for the awesome example. Nice point about SEO, def. need to include it. I see you used a server component in your example which means rendering on request base right? I am very new to Next, but isn't that different from statically generating the page up front?
@Holland Lop <@743561772069421169> Thx for the awesome example. Nice point about SEO, def. need to include it. I see you used a server component in your example which means rendering on request base right? I am very new to Next, but isn't that different from statically generating the page up front?
yes, it can be static generated and its static generated by default
@Holland Lop that's a must read, it's up to date to the App Router and shows static, dynamic and client-side rendering: https://nextjs.org/learn
Holland LopOP
@Eric Burel Are these concept also covered in the course you linked?
Holland LopOP
@Eric Burel especially this part I am interested in: "the client component will call a route handler to get the data and display them" as currently the team is planning on using Opennext instead of vercel and it has no support for partial prerendering.
Holland LopOP
@Ray Inside the useEffect in your example I would call the route handler I assume? I still need to look into the 'learn' guide I think as I fail to see how all the other parts would be statically generated.
@Holland Lop <@743561772069421169> Inside the useEffect in your example I would call the route handler I assume? I still need to look into the 'learn' guide I think as I fail to see how all the other parts would be statically generated.
yep, here is the doc for route handler
https://nextjs.org/docs/app/building-your-application/routing/route-handlers
https://nextjs.org/docs/app/building-your-application/routing/route-handlers
Holland LopOP
I feel like I understand it better now, everything seems to be static by default. Me using a component which will make a client side call at the and of the component tree (price component leaf) Will not change it from being static to dynamic right?
@Holland Lop <@769111741098622976> especially this part I am interested in: "the client component will call a route handler to get the data and display them" as currently the team is planning on using Opennext instead of vercel and it has no support for partial prerendering.
Next.js Learn covers all those subjects, my own course focuses more specifically on how they blend with static rendering which is specifically my area (it's a paid course too so not necessarily where you want to get started but I mentioned it because it's on point)
Holland LopOP
Thx for the response, looking into the Learn now first. Will look into your course later this week