Next.js Discord

Discord Forum

Use server components with pages router?

Answered
Ratonero Mallorquin posted this in #help-forum
Open in Discord
Ratonero MallorquinOP
Let's say you have a project where you're using mainly the pages router. Is it possible to use server components within such routes and benefit from streaming behavior of components, RSC etc?

Or are they only related to the app router "world"?
Answered by Rafael Almeida
you can only use them on the app router, but you can have both routers simultaneously in the same project as long as the routes don't conflict with each other
View full answer

9 Replies

you can only use them on the app router, but you can have both routers simultaneously in the same project as long as the routes don't conflict with each other
Answer
Ratonero MallorquinOP
@Rafael Almeida Thank you.

Perhaps you would know the answer to what led my team to this question.

We've used the pages router with a CMS backend, thousands of pages that then gets cached by what I assume is the "full route cache". Our response times are very good, sometimes as low as 15ms for the initial page loud.

This is all handled via a root [[...slug]].js file, returning different CMS pages depending on the slug.

The pages are not available during build, they are dynamically generated after the fact, as the CMS editors publish new pages.
The end result is thousands of pages served lightning fast, perfect!

We're trying to build a new solution based on the app router.

However we are confused if this is even possible with the app router.
If we use the same approach, a root folder and layout and page file, for example src/app/[[...slug]]/page.tsx - then we can serve pages dynamically from the CMS.

But since they're dynamic, we can never utilize the full route cache, and nextjs has to rebuild the pages on every request. Sure, using the data cache via fetch saves lots of rebuild time, but we can't get below 100ms - NextJS still has to evaluate what happens in page.tsx.

Our we trying to use the wrong tool for the job here maybe?
have you tried setting the dynamic variable of the route segment options to error? (https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic)
it is basically the equivalent of getStaticProps from the pages router
Ratonero MallorquinOP
Had not come across that one before, might actually be exactly what we need, thank you!
Documentation there mentions:

This option is equivalent to:
Setting the option of every fetch() request in a layout or page to { cache: 'force-cache' }

We are currently setting
next: {
  revalidate: cacheTime ? cacheTime : 10
  tags: cacheTags || undefined,
},

as option in our fetches, does this mean it will disregard the revalidate settings?
Ratonero MallorquinOP
@Rafael Almeida We successfully implemented this approach, setting dynamic to error!

We can now utilize the full router cache and our response times are closer to 10ms than 70ms 👍 🥳

However, we noticed one bit of a problem, whenever our main page fetch call to the requested slug in src/app/[[...slug]]/page.tsx returns an empty page, we naturally call notFound(); to trigger a 404.
But this gives us a 500 error, only in production, where we can't see the full error.
There is digest: 'DYNAMIC_SERVER_USAGE' which sounds like it's related to this handling of dynamic vs static.

Do you have any idea if it's possible to solve?
If that is the case and if the index page is the only one making problems ( i might have not understood you correctly) But IF those two statements are true:

You could treat the index page differently from all the other pages by using a catch-all segement with only one pair of squre brackets src/app/[...slug]/page.tsx that route would catch everything But the index page.

The index page would have its own logic at src/app/page.tsx
Ratonero MallorquinOP
Ah, sorry, not really main page in that sense, but we have only one page.tsx, which is the main one, which handles ALL routes basically (except a few api routes).
Based on the slug, you get/ask for the corresponding node from the underlying CMS.

I think I figured out the problem, maybe.
Upon 404 we had a redirect check which used a fetch with cache no-store, and using revalidate there instead seems to have resurrected it while maintaining good performance.