Why should I care about ISR in Next.js? 🤔

Have you heard about ISR but don’t get what all the fuss is about? Let’s breakdown some of the common scenarios where ISR can be especially useful.

Incremental Static Regeneration (ISR) is a hybrid rendering method that allows teams to get the best of both worlds when it comes to static and dynamic rendering. Most users experience the speed of a cached static page while editors don’t need to wait for a full rebuild of their app to make changes.

Publish fast, load even faster with revalidatePath

Our website might include a blog managed by a team of editors who write posts in a Content Management System (CMS). Each post uses the same layout.tsx and requires metadata like the author’s name, post category, last updated date, etc. Our editors like to publish new posts everyday but they don’t often make changes to other parts of the website.

Static rendering worked well when the website was new because there weren’t many posts and builds took ~2mins. The CMS would invoke a Deploy Hook on publish and Vercel would do the rest.

However our editors have been busy and the blog has grown to hundreds of posts! Also the dev team added a bunch of shiny new features to routes outside of /blog which gradually increased average build times too. This means that when someone notices a typo it could take half an hour to roll out a fix and even longer if developers are pushing changes at the same time.

So how would this work with ISR?

Instead of the CMS triggering a full rebuild, we can use revalidatePath to tell Vercel to only rebuild the page that was changed. One of our developers will need to setup a new API route (usually called /api/revalidate) that will accept a path parameter so we can tell it which post we changed. For example /blog/post-1. The good news is that editors won’t need to break muscle memory because that publish button in the CMS will still work just the same.

What happens behind the scenes?

When /api/revalidate has finished, it doesn’t actually mean the page has been rebuilt. Vercel knows that this content is stale so when someone opens /blog/post-1 a Serverless Function will start to build the page in the background. Usually this is almost instant but if these pages are really fancy and we’re fetching content from a bunch of different sources it might take a few seconds to complete. In this scenario the first user could still see stale content if the Serverless Function hasn’t finished yet.

The moment regeneration is complete, page data is stored in global Edge Cache. All subsequent users will get fast load times because the page is fetched from their nearest node. This also means that if nobody visits /blog/post-1 the page will not be built, saving us compute time. Time is money baby!

Find and replace with revalidateTag

Maybe one of our editors got married recently and are excited to update all their posts to include their new last name. It would be pretty annoying if we had to manually update every post but luckily our template uses an author component which is consistent across all posts.

Let’s say that our CMS stores a collection of authors which each have their own id. We could use this id as a tag when Next.js fetches author data for our posts. Then when an author is changed in the CMS we can invoke /api/revalidate and pass the author’s id as a tag prop.

Now Vercel will know that every part of the website which references this author should be updated. Again, this doesn’t mean that all of those pages are instantly rebuilt though. Maybe the really old blog posts don’t get much traffic anymore so we can save some compute time by skipping until someone visits them.

Does this mean we’re fetching the entire blog post again?

Nope! Serverless Functions will only need to reach out to the CMS once to fetch the new author’s name before its stored in Data Cache. This gives subsequent Serverless Function invocations super fast read times and prevents unnecessary (often slow) API calls. There’s a good chance the rest of the post is sitting in Data Cache already too.

New content around the clock with Time-Based Revalidation

Sometimes not everything on a website is changed by a human. Maybe we’d like to add a cute rain animation when its a rainy day or remind users to wear sunscreen when the UV index is high. We could fetch this data from an API every time a user loads the homepage but that would quickly add up and could result in slow page loads. It might be better to fetch it once a day instead.

Technically we could setup Cron Job that runs every 24h and calls a Deploy Hook. But that’s a lot of work considering we’re only showing the weather on the homepage.

Luckily Next.js allows us to specify a revalidation interval at the route level with one line:

export const revalidate = 86400; // invalidate every 24 hours

This tells Vercel that the page needs to be rebuilt once a day, and the platform takes care of the rest. No need to manually trigger deployments or worry about the cost of a full rebuild.

Ok but what if its not just the homepage?

Great question! Routes are not the only place we can define revalidate durations. If multiple pages use the same data we could fetch it once and then import it as many times as we need. To achieve this we just need to include the revalidate prop within our fetch() like this:

fetch("https://...", { next: { revalidate: 86400 } });

Hopefully these examples were helpful! Have you used ISR to solve a different kind of problem? We’d love to hear about it in the comments :star_struck:

5 Likes

I have used ISR for a blog I was working on (it’s no longer online).
I didn’t understand it very well, but now you’ve got me convinced to try it out on some of my other Next.js projects! :smiley:

2 Likes