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/incremental-regeneration

40 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Unlisted params with partial prerendering

When generateStaticParams lists specific params, unlisted params show ◐ and serve the static shell while content streams. When a user visits an unlisted param, Next.js serves the static shell immediately while content streams in, then upgrades the page in the background. This applies Incremental Static Regeneration with Cache Components.

Upgrade result types after first visit

After the first visit, Next.js renders the page in the background with known params and tries to push the static boundary as far down the component tree as possible. The upgrade can produce: a fully static page if all data access is cached and all params are resolved; a cached page with fallbacks if all params are resolved but the render hits uncached data or runtime APIs wrapped in Suspense boundaries; or a partially upgraded page if params are not fully resolved.

Selecting which routes to prerender

Not every route needs to be prerendered. Use generateStaticParams to prerender routes that benefit most from being ready ahead of time, such as popular pages or predictable content. Less frequently visited routes are generated on demand and upgraded after their first visit, avoiding unnecessary build time and storage on pages that may never be requested.

Migration from Pages Router fallback behavior

When migrating from Pages Router: fallback: true in getStaticPaths is now the default behavior with cacheComponents (visitors get Suspense fallback instantly and content streams in); router.isFallback is not needed (prerendering generates a static shell upgradeable with 'use cache'); getStaticProps with revalidate maps to 'use cache' with cacheLife; getStaticPaths maps to generateStaticParams.

App Shell served from Next.js 16.3 for unlisted params

App Shells for unlisted params are served from Next.js 16.3 onwards. Earlier versions wait for a full server render before sending the response.

Incremental Static Regeneration with Cache Components overview

Incremental Static Regeneration (ISR) with cacheComponents and Partial Prefetching allows every route to have an instant first visit, even for URLs that weren't included in the build. During build, Partial Prerendering splits each render into two parts: the App Shell (generic, reusable part of the page that doesn't depend on URL data) and the rest of the statically renderable content (param-specific prerenders for URLs listed in generateStaticParams).

Cache Components vs Pages Router ISR and fallback true

Cache Components with Partial Prefetching is the App Router equivalent to ISR or fallback: true in the Pages Router. For a visit to a URL whose params were included in generateStaticParams, Next.js serves the fully prerendered page from cache. For a visit to a URL whose params weren't, Next.js serves the App Shell instantly, then upgrades it in the background with the now-known params. Subsequent visits to that URL get the upgraded result from cache, skipping the App Shell entirely.

Enable Cache Components and Partial Prefetching configuration

To enable ISR with Cache Components, set both cacheComponents and partialPrefetching to true in next.config.ts. Cache Components produces the App Shell, while Partial Prefetching upgrades it to a full route once the params are known. Configuration example: ```ts import type { NextConfig } from 'next' const nextConfig: NextConfig = { cacheComponents: true, partialPrefetching: true, } export default nextConfig ```

App Shell structure with Suspense boundaries

To allow Next.js to generate an App Shell for unknown params, do not await params at the layout level. Instead, pass the params promise to a component inside a Suspense boundary and await it there. This structure allows the layout's App Shell to be generated separately from specific param values. Even for params covered by generateStaticParams, keep the await inside the Suspense boundary to avoid tying the layout's App Shell to a specific URL.

Runtime behavior of first visit to unknown params

When a visitor navigates to a URL with params not included in generateStaticParams, Next.js serves the App Shell instantly. For nested routes where some params are known and others are unknown, Next.js serves a partially rendered shell with known params rendered and unknown params showing fallback UI. The full page is rendered in the background, and subsequent visits to the same URL get the upgraded result from cache.

Build time prerendering with Cache Components

When running next build with Cache Components, Next.js prerenders routes for param values listed in generateStaticParams, plus one additional render where await params suspends to produce the App Shell. For nested dynamic routes, it prerenders combinations of known param values from parent and child routes. For unknown param combinations, it produces App Shells where await params suspends.

fetch with revalidate 0 or no-store makes route dynamic

If any fetch request on a route has a revalidate time of 0 or an explicit no-store, the entire route is dynamically rendered instead of being prerendered.

Proxy not executed for on-demand ISR requests

Proxy middleware will not be executed for on-demand ISR requests, meaning any path rewrites or logic in Proxy will not be applied. Ensure you are revalidating the exact path, for example /posts/1 instead of a rewritten /post-1.

Multiple instances require custom cache handler for coordination

When running multiple instances, the default file-system cache is per-instance. On-demand revalidation only invalidates the instance that receives the call. To coordinate across instances, use a shared custom cache handler configured via incrementalCacheHandlerPath.

Background regeneration counts as compute on per-request billing

Background regeneration (stale-while-revalidate) runs on the instance that receives the triggering request. On platforms with per-request billing, this background work counts as additional compute.

x-nextjs-cache response header shows cache behavior

The x-nextjs-cache response header indicates cache behavior. Values are: HIT (served from cache), STALE (served from cache, revalidating in background), MISS (not in cache, rendered fresh), or REVALIDATED (regenerated via on-demand revalidation).

revalidatePath example Server Action

This Server Action invalidates the cache for the /posts route: 'use server'\nimport { revalidatePath } from 'next/cache'\n\nexport async function createPost() {\n revalidatePath('/posts')\n}

revalidateTag example Server Action

This Server Action invalidates all data tagged with 'posts': 'use server'\nimport { revalidateTag } from 'next/cache'\n\nexport async function createPost() {\n revalidateTag('posts', 'max')\n}

App Router ISR minimal example with generateStaticParams

Example showing ISR in App Router: export const revalidate = 60 export async function generateStaticParams() { const posts = await fetch('https://api.vercel.app/blog').then((res) => res.json()) return posts.map((post) => ({ id: String(post.id), })) } export default async function Page({ params }: { params: Promise<{ id: string }> }) { const { id } = await params const post = await fetch(`https://api.vercel.app/blog/${id}`).then((res) => res.json()) return ( <main> <h1>{post.title}</h1> <p>{post.content}</p> </main> ) } GenerateStaticParams enables ISR for the dynamic route by returning the list of posts to prerender. During next build, a page is prerendered for each post. All requests to these pages are cached and instantaneous. After 60 seconds, the next request returns the cached stale page, the cache is invalidated and a new version generates in the background. Once generated, the next request returns the updated page. If a new post is requested that exists, it will be generated on-demand (behavior controlled by dynamicParams). If the post does not exist, 404 is returned.

Pages Router ISR minimal example with getStaticPaths and getStaticProps

Example showing ISR in Pages Router with getStaticPaths and getStaticProps: export const getStaticPaths = async () => { const posts = await fetch('https://api.vercel.app/blog').then((res) => res.json()) const paths = posts.map((post) => ({ params: { id: String(post.id) }, })) return { paths, fallback: 'blocking' } } export const getStaticProps = async ({ params }: { params: { id: string } }) => { const post = await fetch(`https://api.vercel.app/blog/${params.id}`).then((res) => res.json()) return { props: { post }, revalidate: 60, } } export default function Page({ post }) { return ( <main> <h1>{post.title}</h1> <p>{post.content}</p> </main> ) } During next build, all known blog posts are generated. All requests to these pages are cached and instantaneous. After 60 seconds, the next request returns the cached stale page, the cache is invalidated and a new version generates in the background. Once generated, the next request returns the updated page. If a new post is requested that exists, it will be generated on-demand (behavior controlled by fallback). If the post does not exist, 404 is returned.

Time-based revalidation example with high interval

This example fetches and displays a list of blog posts on /blog with a 3600 second (1 hour) revalidation interval: export const revalidate = 3600 export default async function Page() { const data = await fetch('https://api.vercel.app/blog') const posts = await data.json() return ( <main> <h1>Blog Posts</h1> <ul> {posts.map((post) => ( <li key={post.id}>{post.title}</li> ))} </ul> </main> ) } After an hour, the next visitor receives the cached stale version immediately for a fast response. Simultaneously, Next.js triggers regeneration in the background. Once generated, it replaces the cached version and subsequent visitors receive the updated content.

fetch with tags example using next: { tags }

Example tagging individual fetch calls for granular revalidation: export default async function Page() { const data = await fetch('https://api.vercel.app/blog', { next: { tags: ['posts'] }, }) const posts = await data.json() // ... }

unstable_cache example with tags and revalidate

Example using unstable_cache with database queries for granular revalidation: import { unstable_cache } from 'next/cache' import { db, posts } from '@/lib/db' const getCachedPosts = unstable_cache( async () => { return await db.select().from(posts) }, ['posts'], { revalidate: 3600, tags: ['posts'] } ) export default async function Page() { const posts = getCachedPosts() // ... }

Pages Router res.revalidate() API example

Example API Route for on-demand revalidation in Pages Router: export default async function handler(req, res) { if (req.query.secret !== process.env.MY_SECRET_TOKEN) { return res.status(401).json({ message: 'Invalid token' }) } try { await res.revalidate('/posts/1') return res.json({ revalidated: true }) } catch (err) { return res.status(500).send('Error revalidating') } } This API Route can be called at /api/revalidate?secret=<token> to revalidate a given blog post. Use a secret token only known by your Next.js app to prevent unauthorized access. If there is an error, Next.js continues to show the last successfully generated page.

Pages Router error handling in getStaticProps

Example showing error handling in Pages Router ISR: export const getStaticProps = async ({ params }: { params: { id: string } }) => { const res = await fetch(`https://api.vercel.app/blog/${params.id}`) const post = await res.json() if (!res.ok) { throw new Error(`Failed to fetch posts, received status ${res.status}`) } return { props: { post }, revalidate: 60, } } If this request throws an uncaught error, Next.js will not invalidate the currently shown page and will retry getStaticProps on the next request. Throwing an error instead of returning prevents the cache from updating until the next successful request.

Debug cached data locally with logging config

Add logging configuration to next.config.js to debug which fetch requests are cached or uncached: module.exports = { logging: { fetches: { fullUrl: true, }, }, }

Enable ISR debugging with NEXT_PRIVATE_DEBUG_CACHE

To debug ISR cache hits and misses in production environment, add NEXT_PRIVATE_DEBUG_CACHE=1 to your .env file. This makes the Next.js server console log ISR cache hits and misses, showing which pages are generated during next build and how pages are updated as paths are accessed on-demand.

Verify ISR behavior locally with next build and next start

To verify pages are cached and revalidated correctly in production, run next build and then next start to run the production Next.js server. This allows you to test ISR behavior as it would work in a production environment.

ISR only supported with Node.js runtime

ISR is only supported when using the Node.js runtime, which is the default. ISR is not supported when creating a Static Export.

ISR deployment platform support

ISR deployment support: Node.js server - Yes, Docker container - Yes, Static export - No, Adapters - Platform-specific. Configure ISR when self-hosting Next.js.

ISR enables updates without full site rebuild

Incremental Static Regeneration (ISR) enables you to update static content without rebuilding the entire site, reduce server load by serving prerendered static pages for most requests, ensure proper cache-control headers are automatically added to pages, and handle large amounts of content pages without long next build times.

Time-based revalidation with revalidate export

In the App Router, export a revalidate constant to set time-based cache invalidation in seconds. For example, export const revalidate = 60 invalidates the cache at most once every 60 seconds. After the time has passed, the next request returns the cached stale page immediately, Next.js triggers regeneration in the background, and once complete, the new version replaces the cached version.

generateStaticParams enables ISR for dynamic routes

In the App Router, use generateStaticParams to enable ISR for dynamic routes by returning the list of parameters to prerender. During next build, a page is prerendered for each parameter set. All requests to these pages are cached and instantaneous. If a route segment is requested that was not generated, the behavior depends on the dynamicParams setting.

On-demand revalidation with revalidatePath

Use the revalidatePath function in a Server Action or Route Handler to invalidate cached pages on-demand. This function invalidates the cache entries and regeneration happens on the next request. The next request to that route will trigger regeneration and serve fresh data, which will then be cached for subsequent requests.

On-demand revalidation with revalidateTag

Use revalidateTag for granular control over which cached entries to invalidate. Tag individual fetch calls with next: { tags: ['tagname'] }. With unstable_cache, pass tags in the options object as { revalidate: 3600, tags: ['tagname'] }. Then call revalidateTag('tagname') in a Server Action or Route Handler to invalidate all data tagged with that tag.

revalidateTag second parameter is 'max'

When calling revalidateTag, the second parameter is 'max', for example: revalidateTag('posts', 'max').

Pages Router ISR with getStaticProps revalidate

In the Pages Router, use getStaticProps to return a revalidate property in seconds to enable ISR. For example, return { props: { post }, revalidate: 60 } invalidates the cache at most once every 60 seconds. Use getStaticPaths to specify which routes to prerender, with fallback: 'blocking' to generate routes on-demand that were not pregenerated.

Pages Router on-demand revalidation with res.revalidate()

In the Pages Router, use res.revalidate() in an API Route to generate a new page on-demand. This is a more precise method than time-based revalidation. For example, await res.revalidate('/posts/1') generates a new version of that page. When using on-demand revalidation, you do not need to specify a revalidate time inside getStaticProps; Next.js will use the default value of false and only revalidate on-demand when res.revalidate() is called.

Error handling in ISR retries on next request

If an error is thrown while attempting to revalidate data, the last successfully generated data continues to be served from the cache. On the next subsequent request, Next.js retries revalidating the data.

Multiple fetch revalidate frequencies use lowest time

If a prerendered route has multiple fetch requests with different revalidate frequencies, the lowest time is used for ISR. However, those revalidate frequencies are still respected by the cache for individual fetch calls.

Give your agent this brain