What is Incremental Static Regeneration - ISR in Next.js?
In the previous tutorials, we explored Revalidate and On-Demand Revalidation in detail. You’ve already learned how to keep your static pages up-to-date either automatically at fixed intervals or manually when content changes. Now, let’s dive into something more powerful and flexible: Incremental Static Regeneration (ISR).
While Revalidate allows you to update already statically generated pages and On-Demand Revalidation gives you real-time control over when pages refresh, ISR introduces something unique—it lets you generate pages on demand, incrementally, without having to regenerate the entire app or rely on pre-building every single page.
What Is Incremental Static Regeneration (ISR)?
ISR allows your application to incrementally generate new static pages and keep them updated. Instead of pre-building all pages at once, ISR generates pages the first time they are requested, caching them for future visitors. It then automatically revalidates these pages based on the revalidation interval you set. This makes ISR perfect for scalability and performance.
Why Use ISR Over Revalidation and On-Demand Revalidation?
You might wonder, “Is ISR really different from the revalidation strategies we’ve already covered?”
Here’s what sets ISR apart:
- Incremental Page Generation: With ISR, you don’t need to generate all pages at build time. Instead, ISR can generate pages as users visit them, which helps when you have thousands of pages (like a recipe app) that don’t all need to be pre-built.
- Automatic Caching and Regeneration: Unlike On-Demand Revalidation, which requires you to manually trigger page updates, ISR will automatically revalidate pages at set intervals based on traffic. This means the system is mostly self-sustaining, requiring little intervention from you.
How ISR Works in a Recipe App
As we covered earlier, ISR allows your app to incrementally generate static pages as users request them. But what if you want to pre-generate a specific set of popular pages at build time and leave the rest to be generated on demand? This is where generateStaticParams
comes into play.
What Is 'generateStaticParams()'
generateStaticParams
is a function that tells Next.js which dynamic paths should be pre-rendered at build time. You can use it to pre-generate a subset of pages (e.g., popular recipes) and let ISR handle the rest.
This combination gives you control over which pages are immediately available after the build and which are generated incrementally when requested.
How to Use 'generateStaticParams()' with ISR
In your Recipe App, let’s say you want to pre-generate the top 5 most popular recipes at build time and use ISR to handle the rest.
src/
└── app/
├── recipes/
│ ├── [id]/
│ │ └── page.tsx # Recipe detail page using ISR
Recipe Detail Page with ISR and 'generateStaticParams()'
// src/app/recipes/[id]/page.tsx
import { fetch } from 'next/navigation';
// Revalidate the page every 24 hours (86400 seconds)
export const revalidate = 86400;
// Pre-generate top 5 most popular recipes at build time
export async function generateStaticParams() {
// Fetch only the most popular recipes (e.g., top 5)
const popularRecipes = await fetch('https://api.vercel.app/recipes/popular').then(res => res.json());
return popularRecipes.map((recipe) => ({
id: recipe.id.toString(), // Return an array of paths like [{id: '1'}, {id: '2'}, ...]
}));
}
export default async function RecipeDetail({ params }) {
const recipe = await fetch(`https://api.vercel.app/recipes/${params.id}`).then(res => res.json());
return (
<section>
<h2>{recipe.name}</h2>
<p>{recipe.description}</p>
<ul>
{recipe.ingredients.map((ingredient) => (
<li key={ingredient.id}>{ingredient.name}</li>
))}
</ul>
</section>
);
}
generateStaticParams
: This function tells Next.js to pre-generate the paths for the top 5 most popular recipes during the build. It fetches the most popular recipes and returns an array of theirid
values, which are used to create static pages.- If the API returns recipes like
[{ id: 1 }, { id: 2 }, ...]
, Next.js will pre-render/recipes/1
,/recipes/2
, etc. - ISR with Revalidation: For all other recipe pages not covered in
generateStaticParams
, ISR will generate them on demand the first time they are requested. These pages are then cached and revalidated every 24 hours based on theexport const revalidate = 86400;
.
Benefits of 'generateStaticParams()' with ISR
By using generateStaticParams
, you can:
- Pre-generate Critical Pages: Ensure that the most important or frequently visited pages (e.g., top recipes) are immediately available to users after the build.
- Scale Efficiently with ISR: Let ISR handle the rest of your pages incrementally. For example, if you have thousands of recipes, you don’t need to build them all upfront. Only generate what’s critical, and let ISR handle the long tail of lesser-visited pages.
Using ISR for Large Content Sets
Use Case:
You have 10,000 recipes, but you only want to pre-generate the top 100 recipes (like “Chocolate Cake” or “Pasta Alfredo”) at build time. Use generateStaticParams
for those 100 and let ISR handle the rest when they are requested by users.
Example:
- Pre-build only the most frequently visited pages (e.g., "Chocolate Cake").
- Other recipes like "Vegan Brownies" are generated only when a user requests that specific page.
How ISR Differs from Revalidate and On-Demand Revalidation
Here’s a quick recap of the differences between ISR, Revalidate, and On-Demand Revalidation:
- ISR: Generates pages incrementally, only when they are first requested. It automatically revalidates pages based on a set interval (e.g., every 24 hours), making it great for scaling large sites.
- Revalidate: Updates pre-built pages at fixed intervals but requires you to generate all pages at build time.
- On-Demand Revalidation: Manually triggers page updates based on events, such as when content is edited.
Scenario Comparison
- Revalidate: Use this when you want to periodically refresh your pre-built pages (e.g., refreshing the recipe list every hour).
- On-Demand Revalidation: Use this when you need immediate updates for pages that reflect real-time changes, such as editing a recipe (covered in [our previous tutorial]).
- ISR: Use this when you have many pages (like recipe detail pages) that don’t need to be pre-built but should be generated incrementally as users request them.
Benefits of Using ISR
ISR gives you a scalable solution to keep pages up-to-date without the overhead of rebuilding your entire app. Here are the key benefits:
- Faster Build Times: You only generate critical pages during deployment, while ISR takes care of generating the rest as needed.
- Automatic Updates: Pages are automatically regenerated based on the revalidation interval you set (e.g., 24 hours).
- Improved Performance: By serving statically generated pages, you improve load times, even for pages that haven’t been visited before.
Conclusion
Incremental Static Regeneration (ISR) in Next.js 14 provides a powerful and efficient way to scale content-heavy apps like a Recipe App. By combining the benefits of static generation with dynamic updates, ISR ensures that your app stays fast, scalable, and up-to-date.
Here’s a quick summary of what ISR brings to the table:
- Incremental Page Generation: Generate new pages on demand when users visit them.
- Automatic Revalidation: Keep pages fresh with automatic revalidation at defined intervals.
- Scalability: Ideal for apps with large content sets, such as recipe collections, where not all pages need to be built at once.
By using ISR, you can ensure that your site scales efficiently while keeping content up-to-date without the need for frequent rebuilds.