new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Next.js · Guides · all subjects

building/prerendering

114 notes in this subject, read out of this brain and free to use. This is page 2 of 2.

Portability: Next.js single Node.js process handles all features

Next.js runs as a Node.js server process where a single process handles every feature correctly. Streaming support enables progressive delivery of Server Components and PPR; without it, responses are buffered but features still work. Additional infrastructure investments (CDN caching, edge compute, shared cache) improve performance and in multi-instance deployments reduce consistency gaps.

CDN PPR resume support still emerging

Many CDNs have useful primitives for deeper Next.js integration (edge compute, key-value storage, blob storage), but end-to-end PPR resume support is still emerging and may require bespoke platform work. Most community adapters today deploy Next.js as a Node.js server without leveraging CDN-specific primitives.

Runtime prefetching definition and purpose

Runtime prefetching resolves URL data at prefetch time, ready before the user clicks rather than streaming in after. It works with Cache Components when partialPrefetching is enabled. It resolves searchParams and params (URL data) that varies per link, preparing them during the prefetch phase so navigation renders immediately without fallbacks.

Partial Prefetching configuration

To enable runtime prefetching, set both cacheComponents: true and partialPrefetching: true in next.config.ts. This configuration allows prefetching one reusable App Shell per route rather than a separate prefetch per link.

Link prefetch={true} enables runtime prefetching

Runtime prefetching is opted into per link with <Link prefetch={true}>. Without this prop, the default behavior prefetches only the App Shell without resolving per-link URL data.

How runtime prefetching resolves URL data

When a Link with prefetch={true} enters the viewport, the router prefetches a prerender that resolves the destination route's URL data before the user clicks. The URL comes from the link's href, known at prefetch time. The prerender advances through anything static or cached, then stops at uncached reads and falls back to the surrounding Suspense boundary.

Cost of runtime prefetching

Runtime prefetching generates a server invocation per prefetchable link, so it is opt-in per link rather than automatic. On pages where all content is statically renderable, Next.js serves the prefetch from static cache instead. A page that accesses non-static data is prefetched at runtime.

Session data vs URL data in prefetching

Session data (from cookies() or headers()) is handled separately from URL data. A route that reads session data gets an App Shell that includes its session data, cached per session on the client and ready on navigation without a per-link runtime prefetch.

When to use runtime prefetching

Use runtime prefetching on routes where: (1) part of the component tree depends on URL data (full URL, searchParams, or params not resolved by generateStaticParams), (2) that part has a known cache lifetime expressible with 'use cache' or 'use cache: private', and (3) the traffic justifies the per-link server invocation.

When to skip runtime prefetching

Skip runtime prefetching when: (1) the route has little or no URL-data dependency (the App Shell already makes navigation instant), (2) dependent content must be fresh on every request (prerender stops at the same Suspense fallback), or (3) the route is rarely navigated to (you pay per visible link regardless of click-through).

App Shell vs per-link runtime prefetch comparison

App Shell prefetching has one per route, contains route rendered output minus per-link data, cost bounded by route count, and serves as every route's instant floor. Per-link runtime prefetch with prefetch={true} has one per visible Link, contains same content plus per-link URL data resolved, cost bounded by visible-link count, and upgrades to more rendered before click.

Best-effort nature of runtime prefetching

A per-link runtime prefetch is best-effort. It only helps navigations where it completes before the user clicks. On slow connections, feeds of many links, or direct visits, it may not be ready when navigated to, and falls back to the App Shell. The shell is the reliable baseline, and runtime prefetching layers on top when it arrives in time.

Hover-triggered prefetch as alternative to per-link prefetch

When many links to a route are visible at once (such as a grid of cards), each Link with prefetch={true} prefetches as it enters the viewport, creating one server request per card. Use hover-triggered prefetch instead to fetch only links the user is likely to click. The default Link (without prefetch={true}) prefetches only the App Shell without this cost.

Cold cache behavior in runtime prefetching

A cold cache (first visit or after expiration) means the server still has to compute the cached result. Users may see a loading spinner on that first navigation. Subsequent navigations are instant as long as the cache is warm.

Params handling with runtime prefetching

Like searchParams, params needs a Suspense boundary even when values are predefined by generateStaticParams. A statically known param still belongs to one URL. Runtime prefetching resolves the values generateStaticParams does not cover.

Runtime prefetching example with searchParams

Example: A page at / has links to /search?q=react and /search?q=next with prefetch={true}. The destination SearchPage renders a static heading and a Results list whose contents depend on the query. Each query is cached and computed once. Without prefetch={true}, clicking shows the Results fallback until the query resolves. With prefetch={true}, the router prefetches a prerender that resolves the Results before the click using the q value from the link's URL, so results render immediately on click.

Static export advantages for SPA

Next.js supports generating fully static site, with advantages over strict SPAs: (1) Automatic code-splitting instead of single index.html, Next.js generates HTML file per route so visitors get content faster without waiting for client JavaScript bundle; (2) Improved user experience with fully rendered pages for each route instead of minimal skeleton for all routes. When users navigate client side, transitions remain instant and SPA-like.

Static exports do not support server features

Next.js server features are not supported with static exports.

Incremental migration guides to Next.js

You can incrementally migrate to Next.js from existing projects by following guides: Migrating from Create React App, Migrating from Vite. If already using SPA with Pages Router, learn how to incrementally adopt App Router through the app-router-migration guide.

CSP nonce requirement for dynamic rendering

Nonces require dynamic rendering because Next.js applies nonces during server-side rendering based on the CSP header in the request. Static pages are generated at build time when no request or response headers exist, so no nonce can be injected. Every page view must generate a fresh nonce, which is why dynamic rendering is mandatory for nonce-based CSP.

Using connection() to force dynamic rendering in App Router

In Next.js App Router, use `await connection()` from 'next/server' in a page component to force dynamic rendering. This ensures the page waits for an incoming request to render, which is necessary when using nonces in CSP since static generation cannot have nonces.

Partial Prerendering incompatible with nonce-based CSP

Partial Prerendering (PPR) is incompatible with nonce-based CSP because static shell scripts won't have access to the nonce. Nonces require dynamic rendering for every request.

Performance implications of nonce-based CSP

Using nonces in CSP has performance implications: pages must be dynamically rendered, resulting in slower initial page loads, increased server load, no CDN caching by default, and higher hosting costs since every request requires server-side rendering. Static optimization and ISR are disabled.

Partial Prefetching codemod (16.3)

The remove-partial-prefetch codemod removes `export const prefetch = 'partial'` from page and layout files. Run with `npx @next/codemod@canary remove-partial-prefetch ./app`. It only removes the 'partial' value and leaves other values like prefetch = 'force-disabled' in place. For src/ projects, use ./src/app as the path.

Prefetch scheduling order

Next.js maintains a small task queue and prefetches in the following order: (1) Links in the viewport, (2) Links showing user intent (hover or touch), (3) Newer links replace older ones, (4) Links scrolled off-screen are discarded.

Client-side transition after prefetch

When navigating to a prefetched page, there is no full page reload or browser loading spinner. Next.js performs a client-side transition, making the page navigation feel instant.

Prefetching definition and purpose

Prefetching makes navigating between routes feel instant by fetching page resources like HTML and JavaScript files ahead of time, before the user navigates to a new route.

Default prefetching behavior in production

Next.js prefetches automatically in production. As each <Link> enters the viewport, Next.js prefetches the route behind it and schedules the work so a page full of links does not flood the network.

Prefetching static routes

Without Cache Components, a static route is prefetched in full. The Client Cache TTL is 5 minutes by default (controlled by staleTimes.static). No server roundtrip occurs on click.

Prefetching dynamic routes

Without Cache Components, a dynamic route is skipped from prefetching unless it has a loading.js boundary. The Client Cache TTL is off by default (unless enabled via staleTimes). A server roundtrip occurs on click, with content streamed after shell.

Automatic prefetch with no loading.js

When a <Link> has no loading.js boundary, the entire page is prefetched with a Client Cache TTL of 5 minutes (staleTimes.static).

Automatic prefetch with loading.js

When a <Link> has a loading.js boundary, only the layout to the first loading boundary is prefetched. The Client Cache TTL is off by default (staleTimes.dynamic).

Prefetching disabling

Automatic prefetching runs only in production and can be disabled per link with prefetch={false}.

Code splitting and prefetching

Next.js automatically splits the application into smaller JavaScript chunks based on routes. Instead of loading all code upfront like traditional SPAs, only the code needed for the current route is loaded, reducing initial load time while other parts are loaded in the background.

Manual prefetch with useRouter

To prefetch manually, import the useRouter hook from next/navigation and call router.prefetch() to warm routes outside the viewport or in response to analytics, hover, or scroll.

Hover-triggered prefetch implementation

To defer prefetching until a user hovers over a link, set prefetch={false} initially and then set prefetch={null} on mouse enter. prefetch={null} restores default (static) prefetching once the user shows intent.

Disabling prefetch for specific links

You can fully disable prefetching for certain routes using prefetch={false} on the <Link> component. This means static routes will only be fetched on click, and dynamic routes will wait for the server to render before navigating.

Side-effects during prefetching problem

If layouts or pages are not pure and have side-effects (e.g., tracking analytics), Next.js might run them when the route is prefetched, not when the user visits the page.

Moving side-effects away from layout root

To avoid side-effects during prefetching, move side-effects to a useEffect hook or a Server Action triggered from a Client Component, rather than running them directly in the layout or page root.

Router.prefetch onInvalidate callback

When using router.prefetch() with a custom prefetching strategy, pass an onInvalidate callback. Next.js invokes onInvalidate when it suspects cached data is stale, so you can refresh the prefetch.

Extended Link component maintenance

Extending the <Link> component to create a custom prefetching strategy opts you into maintaining prefetching, cache invalidation, and accessibility concerns. This should only be done when the defaults are insufficient.

Preventing full page navigation with custom link

When creating a custom link component using an <a> tag instead of <Link>, use onClick to prevent the default full page navigation, then call router.push to navigate on the client.

Large list prefetching mitigation

For large lists of links (e.g., infinite scroll tables), disable prefetching by setting prefetch={false} on the <Link> component to avoid unnecessary resource usage, or defer prefetching until hover instead.

Enable static export with output configuration

To enable a static export in Next.js, set `output: 'export'` in next.config.js. When running `next build`, Next.js generates an HTML file per route and creates an `out` folder with all HTML/CSS/JS assets.

Optional static export configuration options

The next.config.js static export supports these optional settings: `trailingSlash` (boolean, default false) changes links `/me` -> `/me/` and emits `/me.html` -> `/me/index.html`; `skipTrailingSlashRedirect` (boolean, default false) prevents automatic `/me` -> `/me/` redirect and preserves `href`; `distDir` (string, default 'out') changes the output directory.

Server Components in static export

When running `next build` for a static export, Server Components in the app directory run during the build process, similar to traditional static-site generation. The resulting component is rendered into static HTML for initial page load and a static payload for client navigation between routes. No changes are required unless Server Components consume dynamic server functions.

Route Handlers with static export

Route Handlers render a static response when running `next build` with static export. Only the GET HTTP verb is supported. To ensure Route Handlers are prerendered, explicitly mark the handler as static by adding `export const dynamic = 'force-static'`.

Browser APIs in static export prerendered components

Client Components are prerendered to HTML during `next build`. Web APIs like `window`, `localStorage`, and `navigator` are not available on the server, so they must be safely accessed only when running in the browser, typically within a `useEffect` hook.

Static export unsupported features in App Router

The following features are not supported with static export in App Router: Dynamic Routes with `dynamicParams: true`, Dynamic Routes without `generateStaticParams()`, Route Handlers that rely on Request, Cookies, Rewrites, Redirects, Headers, Proxy, Incremental Static Regeneration, Image Optimization with default loader, Draft Mode, Server Actions, and Intercepting Routes. Attempting to use these with `next dev` results in an error similar to setting `dynamic: 'error'`.

Static export build output structure

After running `next build` with static export, Next.js generates an `out` folder. For example, routes `/` and `/blog/[id]` generate files: `/out/index.html`, `/out/404.html`, `/out/blog/post-1.html`, and `/out/blog/post-2.html`.

Route Handler static export example

To render a static Route Handler in static export, use `export const dynamic = 'force-static'` at the top of the route file. Example: a GET handler in `app/data.json/route.ts` with `export const dynamic = 'force-static'` and `export async function GET()` returning `Response.json({ name: 'Lee' })` produces a static `data.json` file during build.

Static export use case: start as static then upgrade

Next.js enables starting as a static site or Single-Page Application (SPA), then later optionally upgrading to use features that require a server. Breaking a strict SPA into individual HTML files per route avoids loading unnecessary JavaScript on the client-side, reducing bundle size and enabling faster page loads.

Version history of static export feature

In v13.3.0, `next export` was deprecated and replaced with `output: 'export'`. In v13.4.0, App Router (Stable) added enhanced static export support including React Server Components and Route Handlers. In v14.0.0, `next export` was removed in favor of `output: 'export'`.

Next.js prerenders Client Components with Cache Components enabled

With Cache Components enabled, Next.js also prerenders Client Components. Keep queries needed during the initial render behind Suspense to defer that work. TanStack Query can read the current time while creating active query state, and the boundary lets Next.js defer that work instead of raising a current-time prerender error.

Give your agent this brain