DEV Community

Cover image for Incremental Static Regeneration in Nuxt
Jakub Andrzejewski
Jakub Andrzejewski

Posted on

Incremental Static Regeneration in Nuxt

When I first heard the term Incremental Static Regeneration I was instantly interested in exploring how it works and how I could utilize it in my applications.

After reading first paragraphs and watching some introductory videos, I thought to myself; Damn, another solution that works only for Static apps like blogs, what about e-commerce?

And then, I watched the video by @leerob about this topic where he was also showing how to utilize this concept in Next.js based E-Commerce application. And that was something that I really liked!

You can check out the video introduction below:

https://github.com/danielroe/nuxt-vercel-isr

https://vercel.com/blog/nuxt-on-vercel

In this article, I decided to write about how you can achieve the same result in my favourite framework -> Nuxt 💚

The problem

Sites generated statically (SSG's) are great for performance as they are just pure HTML send to the browser. This works great for small apps like blog websites, but for large and complex projects like e-commerce websites, the amount of pages that would need to be prerended is quite huge.

SSG Problem

The bigger the number of pages = the longer build time. And for some companies this is a complete no-go.

The solution

Incremental Static Regeneration (ISR) allows content editors and developers to use static generation on a per-page basis and update content without having to rebuild the entire site.

It uses the concept of cache under the hood to cache the generated template and only rerender it when there is a need for that (for example a new content in CMS is added).

Take a look at the following graphic to understand better how this works.

ISR in details

How to use it in Nuxt?

For such article, I would normally create a demo project and repository but the great @danielroe himself already done that and you can check it out here

Nuxt Vercel

The demo application can also be seen here

You can also read more how to use Nuxt with Vercel here

But the general idea is to utilize the concept of routeRules that allows you to specify how your application should be rendered (read more about hybrid rendering here)



export default defineNuxtConfig({
  routeRules: {
    // all routes will be background revalidated (ISR) at most every 60 seconds
    '/**': { isr: 60 },
    // this page will be generated on demand and cached permanently
    '/static': { isr: true }
  },
});


Enter fullscreen mode Exit fullscreen mode

The above implementation shows how to use ISR in Nuxt but you can also take it to another level and configure your app like following:



export default defineNuxtConfig({
  routeRules: {
    // all routes (by default) will be revalidated every 60 seconds, in the background
    '/**': { isr: 60 },
    // this page will be generated on demand and then cached permanently
    '/static': { isr: true },
    // this page is generated at build time and cached permanently
    '/prerendered': { prerender: true },
    // this page will be always fresh
    '/dynamic': { isr: false },
    // you can do lots more with route rules too!
    '/redirect': { redirect: '/static' },
    '/headers': { headers: { 'x-magic-of': 'nuxt and vercel' } },
    '/spa': { ssr: false },
  },
})


Enter fullscreen mode Exit fullscreen mode

You can clearly see how much control Nuxt gives you while building applications.

Summary

Nicely done! You understand now what are the issues of SSG apps, how you can solve them with ISR, how to achieve ISR in Nuxt and how you can customize the rendering of Nuxt to match your needs. That was a lot but this kind of knowledge is always really useful.

Take care!

Top comments (7)

Collapse
 
lucaargentieri profile image
Luca Argentieri • Edited

Thank you @jacobandrewsky for this post!

I have a question:
I have a blog with a list of articles that could be modified.
I'm using nuxt with ssr:true
I'm building on netlify with the command: yarn build
And when I update the content (from Sanity CMS) the content on the page is updated (without webhook, that is super cool).

So my question is:
What's the difference between what I did and this?

routeRules: {
"/**": { isr: 60 },
},
Enter fullscreen mode Exit fullscreen mode

I mean, the result is the same.
Is it better for performance?

Collapse
 
jacobandrewsky profile image
Jakub Andrzejewski

Hey, good question!

So the difference is that your application is rendered on the server (nitro). This means that each time user visits your page, the server needs to send a request to all sources (like your CMS) and render HTML content based on it.

This works quite well as you mentioned without a webhook.

But the advantage of ISR is that you can have an application that is generated as a static app (no additional logic on the server necessary so it is just pure HTML, CSS) and only revalidate it when needed (for example when a content is updated in CMS).

So you get the advantage of static site generation (which is overall much better for performance) and still be able to have dynamic content being applied to your app through the usage of native caching.

The best usage of ISR is actually when you have a lot of pages (like e-commerce with milions of products) because there a build step will take ages and rebuild after changing some content in another place like CMS will take a lot of time as well. So ISR solves that issue because it only rebuild certain parts of your app when needed and everything else stays unchanged.

This is the magic of ISR 😃

Collapse
 
unluckynelson profile image
Johan

How did you solve the locale problem? As of now RouteRules does not support getKey method to generate custom cache keys for locale specific caches. This means visitors with different currencies settings get served incorrect rendered cached pages. As far as I can tell I would have to write a memory cache plugin myself which renders this feature quite useless for sites serving different currencies.

Collapse
 
jacobandrewsky profile image
Jakub Andrzejewski

Hey,

Very interesting question. I needed to do some research to try to answer you.

Basically, you are correct. There are no ways to define the cache key for route rules right now in Nuxt AFAIK.

The examples that I have found are not caching pages based on locale or currency. They serve the static HTML with the price for the default locale and for others you have to manually change the locale to see the different value.

I think however, that the ability to define the cache key based on the current locale or currency would be really useful (especially in e-commerce) so I already contacted the Nuxt Core Team to talk about this initiative.

I will keep you posted :)

Collapse
 
jacobandrewsky profile image
Jakub Andrzejewski

And I have an update for you as I talked to Nuxt team.

The answer is that you shouldn't cache these kind of things. The better way would be to display appriopriate values on the client side without caching the full page and update it after loading the page for the client with appriopriate value.

You can check following module for reference (it respects the locale even in SSG) -> github.com/danielroe/nuxt-time

Also, there is an option to create a custom handler with varies option that will let you configure your cloud provider to cache based on certain conditions -> nitro.unjs.io/guide/cache#route-ha...

Collapse
 
jordypereira profile image
Jordy

Is it correct that right now (at least in Vercel) Nuxt does not support on demand revalidation of a single ISR cached page?

Collapse
 
jacobandrewsky profile image
Jakub Andrzejewski

Yes, you are correct. The on demand revalidation is not implemented yet. It is possible to have this feature in Vercel in Nitro 2.7 though github.com/unjs/nitro/pull/1723