Course outline · 0% complete

0/29 lessons0%

Course overview →

What makes a page dynamic

lesson 7-2 · ~8 min · 23/29

Next.js decides from your code

You rarely declare a strategy. Next.js infers it. At build time it tries to prerender every page, and a page becomes dynamic when it does something only knowable at request time:

  • Reading cookies or request headers, which identify who is asking.
  • Reading searchParams, as in /search?q=shoes, which describes what was asked for.
  • Fetching uncached data, meaning a plain fetch with no caching opted in.

With no such dependency, the page can be static. Add revalidate and a static page becomes ISR. The strategy is decided per page, so one app freely mixes a static landing page, an ISR blog, and a dynamic dashboard.

The best case: nothing depends on the request

Take a pricing page that renders fixed JSX with no fetches, no cookies, and no searchParams. next build prerenders it to static HTML once, at build time.

Nothing in the page depends on the incoming request, so Next.js can safely render it during the build and serve the identical HTML to every visitor from a CDN. There is no server work per request at all, which makes this the cheapest and fastest outcome available.

Static is the automatic best case, and it is worth noticing that you did not ask for it. You simply avoided request-time dependencies, and the framework drew the obvious conclusion.

Reading the build output

After next build, Next.js prints a route table with a symbol per route: a static/prerendered marker for pages baked at build time, and a dynamic marker for pages rendered per request. Get in the habit of reading it. A page you meant to be static showing up dynamic usually means a stray cookies() call or an uncached fetch snuck in.

This diagnosis skill matters because the symptoms differ: static mistakes look like stale data, dynamic mistakes look like slow pages and server load.

Why a cookie-reading dashboard cannot be static

A dashboard that greets the signed-in user by reading a session cookie cannot be prerendered as static HTML.

Reading a cookie means the output depends on who is asking. At build time there is no request, no cookie jar, and no user, so there is no correct HTML to produce. The page must render dynamically on each request, once per visitor.

That is exactly why cookies(), headers(), and searchParams force dynamic rendering. Each one is a window onto the specific request being served.

Why it works out that way

  • Static HTML is rendered once at build time, before any user exists, so anything user-specific is unanswerable then.
  • One prebuilt file is shared by everyone, and a personalized greeting is by definition not shareable.
  • The alternative would be worse than slow: caching one user's dashboard and serving it to another is a data leak, not an optimization.