Next.js Discord

Discord Forum

NextJS13 force-dynamic

Answered
Dovekie posted this in #help-forum
Open in Discord
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 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 kB


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
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 here
View full answer

38 Replies

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 (/) 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't
the 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 example
then 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 ?
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 / 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 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
yes I'm hosting on AWS-Amplify
hmm looks like it's a bug in your hosting provider...
keep the page component a server component
(so without the use client)
then force-dynamic on it
DovekieOP
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 here
Answer
afaik many segment config exports only work in server components
runtime and metadata are examples
i didn't know dynamic is one of them as well but that is possible
DovekieOP
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 ?
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!