NextJS13 force-dynamic
Answered
Dovekie posted this in #help-forum
DovekieOP
I have a specific page I want to make sure always gets rendered on the server (doesn't get cached).
By reading the docs I believe that
So here is my
When I run
The reason I want to avoid this btw is because this route requires auth and I want middleware to run to check for the user's permissions. The reason why middleware doesn't get to run is because AWS Cloudfront (CDN) has this cached as static content for the user so it just sends it before the middleware even runs
By reading the docs I believe that
export const dynamic = 'force-dynamic should do the trick. So here is my
page.tsx"use client";
import { useAuth } from "@/app/providers/AuthProvider";
import { Button } from "@/components/Button";
export const dynamic = "force-dynamic";
export default function Home() {
const { logout, user } = useAuth();
return (
<div className="min-h-screen">
<h1>
Hello, <span>{user?.nickname}</span>
</h1>
<br />
<Button className="bg-purple-400" onClick={logout}>
Logout
</Button>
</div>
);
}When I run
npm run build though it says that my route will still be statically generated:Route (app) Size First Load JS
┌ ○ / 3.16 kB 81.5 kBThe reason I want to avoid this btw is because this route requires auth and I want middleware to run to check for the user's permissions. The reason why middleware doesn't get to run is because AWS Cloudfront (CDN) has this cached as static content for the user so it just sends it before the middleware even runs
Answered by joulev
it's functionally the same as your existing page
// page.tsx
import PageClient from "./page-client";
export const dynamic = "force-dynamic";
export default function Page() {
return <PageClient />;
}// page-client.tsx
"use client";
// your actual page logic here38 Replies
your page has to be a server component for the server to have something to run
on then can we talk about whether it's run during build time (static rendering) or runtime (dynamic rendering)
DovekieOP
Yeah, you're right with the naming there, that's what I meant to say
if you want it to be rendered on the server at any cost then why do you explicitly declare it as a client component?
DovekieOP
I want it to be dynamically rendered (runtime). The reason it's not a server component is because Im using
useAuth which is my auth provider for my application (client component because it keeps user state etc)DovekieOP
I hope my explanation is clear.
I would like for this page (
Based on the docs I would expect
I would like for this page (
/) to not be rendered during build time. Rather at runtime, for each user request. Based on the docs I would expect
export const dynamic = 'force-dynamic' to do the trick but it doesn'tthe problem is that there is nothing to run during runtime
you are using a client component
so the server has nothing to run
you have to use a server component for dynamic rendering to even make sense
since it's a client component, all the rendering takes place on the browser
the server only needs to prerender a skeleton empty state
so dynamic rendering doesn't make sense
you have to retrieve the auth state on the server using a server component with
cookies for examplethen dynamic rendering will work as expected (even without
"force-dynamic")DovekieOP
Okay I think I get what you're saying and it would be a good practice to follow for my code.
What I don't understand is the following:
NextJS offers SSR, right ? That's not related to client or server components.
It's just being able to render the JS on the server and produce the necessary HTML/CSS files it will send to the client as a "first paint" so the user has something to see, right ?
Correct so far ?
What I don't understand is the following:
NextJS offers SSR, right ? That's not related to client or server components.
It's just being able to render the JS on the server and produce the necessary HTML/CSS files it will send to the client as a "first paint" so the user has something to see, right ?
Correct so far ?
yes, and your route is being SSR'd normally
DovekieOP
Okay so then comes the question, when does NextJS render those routes on the server?
From my understanding there are a few options:
1. The default is that it pre-renders them during build. This is what's happening in my case where when the client goes to
2. No pre-rendering. So there is no page being rendered during build time. SSR only happens when the user requests the page. So the client doesn't receive anything pre-rendered. It still receives an SSR'd first paint, but its calculated during the client's request
From my understanding there are a few options:
1. The default is that it pre-renders them during build. This is what's happening in my case where when the client goes to
/ it gets the page without the middleware being executed (because it just gets it from the CDN).2. No pre-rendering. So there is no page being rendered during build time. SSR only happens when the user requests the page. So the client doesn't receive anything pre-rendered. It still receives an SSR'd first paint, but its calculated during the client's request
Still good or did I miss something ?
@Dovekie Okay so then comes the question, when does NextJS render those routes on the server?
From my understanding there are a few options:
1. The default is that it *pre-renders* them during build. This is what's happening in my case where when the client goes to `/` it gets the page without the middleware being executed (because it just gets it from the CDN).
2. No pre-rendering. So there is no page being rendered during build time. SSR only happens when the user requests the page. So the client doesn't receive anything pre-rendered. It still receives an SSR'd first paint, but its calculated during the client's request
ok this is where it deviates from what normally happens.
This is what's happening in my case where when the client goes to / it gets the page without the middleware being executedare you hosting somewhere other than vercel? because middleware should always be executed when you navigate to
/, CDN or not (unless you send a cache-header telling your browser to cache the page for too long - in that case you need to remove the header)DovekieOP
yes I'm hosting on AWS-Amplify
@joulev ok this is where it deviates from what normally happens.
> This is what's happening in my case where when the client goes to / it gets the page without the middleware being executed
are you hosting somewhere other than vercel? because middleware should always be executed when you navigate to `/`, CDN or not (unless you send a cache-header telling your browser to cache the page for too long - in that case you need to remove the header)
DovekieOP
I'm looking for a way to tell NextJS that it shouldn't statically generate the page on build. Because if it doesn't statically generate it then there will be nothing to store on the CDN
hmm looks like it's a bug in your hosting provider...
@Dovekie I'm looking for a way to tell NextJS that it shouldn't statically generate the page on build. Because if it doesn't statically generate it then there will be nothing to store on the CDN
but if you want to do this, i guess you should move your existing page to a separate component
keep the page component a server component
(so without the
use client)then
force-dynamic on itDovekieOP
Damn...
Original message was deleted
it's functionally the same as your existing page
// page.tsx
import PageClient from "./page-client";
export const dynamic = "force-dynamic";
export default function Page() {
return <PageClient />;
}// page-client.tsx
"use client";
// your actual page logic hereAnswer
afaik many segment config exports only work in server components
runtime and metadata are examplesi didn't know
dynamic is one of them as well but that is possibleDovekieOP
Interesting, I do remember being able to opt out of static rendering (build time rendering) in NextJS12 (where client components where not a thing).
Do you remember this as well ?
Perhaps it's something that could be added back in ?
Do you remember this as well ?
Perhaps it's something that could be added back in ?
that's done by adding
getServerSideProps/getInitialProps, which is equivalent to adding a wrapping server component (my example above)DovekieOP
Aaaaalright, I see
That makes sense
Thank you very much!