Next.js Discord

Discord Forum

Statically render a page using uncached data??

Unanswered
Argente Brun posted this in #help-forum
Open in Discord
Argente BrunOP
How can I render a page statically using uncached data? Ie. the HTML is rendered statically at build time, using un-cached fetch requests

Using { cache: 'no-store' } opts you in to dynamic rendering, even with dynamic = 'force-static' (https://github.com/vercel/next.js/issues/47148 )

😩

36 Replies

@Argente Brun what you can do, is keep the page dynamic, so keep fetch as no store
use this to build the pages on build (xD)
this will make it so only the pages you built on build will be generated using not cached fetch requests
and other pages will be 404
Argente BrunOP
Thanks @Arinji !

It's my understanding that if you have dynamic = 'force-dynamic'and dynamicParams = false, that will 404 for any URLs not returned in generateStaticParams(), but other pages will still render dynamically at request time - is that correct?

I want to render pages statically with fresh data - mostly at build time but with capacity for pages not included in generateStaticParams() which are then rendered once on request then cache.

for 404s, i need to check for redirects defined in my cms backend, but my fetch is being cached.

so:

- A request comes in for a page /foo which is not returned generateStaticParams()
- I check my backend for a redirect for /foo - none is found, so i 404
- Next caches the 404 response?
- A redirect is then added for /foo in the cms
- A new request comes in for /foo but the redirect doesn't work - either because the fetch() is cached or the whole route is cached

i've done a bit of testing with next 15 and it does appear to behave more how i'd expect
Argente BrunOP
I'm actually getting a DYNAMIC_SERVER_USAGE 500 error atm. I'm expecting next to recognise that my /foo route uses dynamic data (uncached fetches) and render that route dynamically, but it seems to expect it to be static for some reason
@Argente Brun it's not as complicated as you make it seem :)
If you want to not always show a 404, just don't let nextjs handle pages you didn't generate
Do it yourself, check for data, and show 404 as you need
also are you using cookies, the DYNAMIC_SERVER_USAGE would come from that
in that case, if you are, add dynamic = 'force-dynamic' as you mentioned before :D
Argente BrunOP
yeah it's a bit convoluted because i'm using url search params (which are dynamic-only like cookies), but only for draft mode requests.

so i'm checking if draft mode is enabled, and only then using dynamic data. i'm not using dynamic = 'force-dynamic' or dynamic = 'force-static' to allow nextjs to dynamically render draft requests but statically render others
@Arinji Do it yourself, check for data, and show 404 as you need
Argente BrunOP
sorry, what do you mean by doing it myself vs let nextjs handle it?
well, im assuming you have a db right?
Argente BrunOP
i think in this case the DYNAMIC_SERVER_USAGE error is coming from fetch(..., {cache: 'no-cache'})
@Argente Brun i think in this case the DYNAMIC_SERVER_USAGE error is coming from fetch(..., {cache: 'no-cache'})
either way, its because we are doing the generateStaticParams without a dynamic export, so any way you need to export dynamic
because without export dynamic, you arent using a server, and when you do any request..you need a server
Argente BrunOP
it's tricky to control the different caching layers without nextjs trying to be clever. eg. if i can't static html cached for routes, but without using caches for the data that route uses 😁
ahh ok, i think i see what you mean, ty
Argente BrunOP
what i expected is that if i had a dynamic route /[slug], which matches urls /foo and /bar, i might need to use dynamic data for /foo but not for /bar.

eg. maybe /foo is returned by generateStaticParams() and is statically rendered at build time, but /bar would dynamically query the db for a matching redirect
Ok so what i would do / mean by doing it yourself is this.
Firstly make it so nextjs dosent show 404 pages, by this i mean setting dynamicParams = true
then next, you can just fetch using the route segment, and cache it with the route segment.

a small example would be
/route/[foo]/page.tsx

and inside page.tsx you have a fetch like this
const res = await fetch(() => { console.log("Fetch Here")}, cache: "force-store", next: {tags: [params.foo]});
(obviously please dont just put that in your code lol, makke sure i didnt make any syntax errors
but yea, now according to this you can just show a 404 if you want, and it will be cached so only if you revalidate the foo page, it will always show 404
Argente BrunOP
ahh i'm with you, tyvm. Then would you use invaldateTag() when a redirect is added in the db?
yes.
If you dont mind me asking, what are you making?
Argente BrunOP
i've removed the cache: no-store which fixes the 500 error but does use cached data.

i have a function handleMissingPage() in my page.tsx and i THOUGHT it was being called for every request (like it would if i used dynamic = 'force-dynamic') and that by fetch() was cached, but it turned out it's not. it's called once for the first request, which i guess makes sense more sense
Argente BrunOP
Not at all, it's a headless app with craft CMS, GQL and ISR. My intention is to:

- Render all craft pages at build time
- When a Craft entry is updated, invalidate the frontend on-demand using an api endpoint with revalidatePath / revalidateTag. Those pages would then re-render on the next request
- For missing pages, dynamically query Craft for redirects defined in the Retour plugin
- Support preview requests using nextjs's draft mode and a url query parameter to identify the draft data to query from craft
It's mostly worked pretty well, i switched from revalidatePath to revalidateTag though which i think exposed some holes in my caching. In hindsight i should have tried to stick to full-page caching with revalidatePath
ah, cause i had a similar need a while ago, for my wiki site
its a company site so cant show code :(
but yea, im not sure if your questions got answered or not xD