Next.js Incremental Static Regeneration

The way developers approach new web applications has changed due to Next.js.  For a long time, dynamic sites used a combination of Server-side Rendering (SSR) and Client-side Rendering (CSR) to display dynamic data in their applications. SSR succeeded well because developers were able to build HTML before passing it on to the browser, allowing search engines to readily crawl it. CSR was also fantastic because it enabled lazy loading of elements, which helped to reduce the initial payload time and bandwidth utilization.

Static pages load faster than pages that are displayed in response to a request. It can be difficult to update if your data changes frequently. Updating your website every time a blogger publishes a new blog for your site might be a time-consuming operation.

Until recently, there were just two serving options:

  1. Static Site Generation (SSG)
  2. Server-side Rendering (SSR)

In Next.js v9.5, however, a new feature called Incremental Static Regeneration (ISR) is introduced, which combines the two.

We will cover the following:

  1. Static Site Generation (SSG) vs. Server-side Rendering (SSR)
  2. Incremental Static Regeneration in Next.js
  3. How does Incremental Static Regeneration Work?
  4. Reason Why ISR isn’t Recommended
  5. When to Use Incremental Static Regeneration?
  6. Examples of Incremental Static Regeneration
  7. ISR: It's More Than Just Caching

Static Site Generation (SSG) vs. Server-side Rendering (SSR)

The time when the HTML for the page is generated is the difference between SSG and SSR. The HTML is created at build time when using SSG. However, SSR creates the HTML for the page with each request.

Static Site Generation (SSG)

A static-site generator is a program or tool that uses raw data and templates to create static HTML websites and pages. Static-Site Generator eliminates the need to manually code HTML pages.

These generators create HTML pages in advance and make them available to the user. This means that a page loads instantly whenever a user wants it. Because the website is static and the generator generates the pages at build time, this happens very quickly.

Content management systems (CMS), such as WordPress, are close relatives of static-site generators. To create and manage web content and pages, a content management tool is utilized. They both make use of templates to avoid manually writing, formatting, and coding web pages.

When a user requests a page from a CMS, the server retrieves the content from the CMS database, fills it into a template that suits the web content, creates the requested page, and sends it to the user on the browser.

Static-Site Generation, on the other hand, employs the same template principle to build pages automatically. Unlike CMS, however, the content is static, and the templates are loaded ahead of time. The pages are ready to be shown on the user's browser right away.

This indicates the server does not make any API requests to render HTML content. During the build-up phase, the pages are rendered. Because they're pre-cached, pre-generated, and pre-rendered, all of your pages will load extremely rapidly.

Vercel and Netlify are common platforms for hosting static websites. You don't need your own database. As a result, using such hosting providers and running statically created pages with automatic builds has never been easier.

Next.js, NuxtJS, Gatsby, Jekyll, and Hugo are some of the most popular Static-Site Generator tools.

Here's an example of an SSG:

export async function getStaticProps() {
	const res = await fetch('https://contently.com/posts');
	const posts = await res.json();

	return {
		props: {
			data: posts
		}
	};
}

A getStaticProps() function should be exported by every static page. The method is called during the construction process, and the props it returns are passed to the React component as props. In this example, we call and return the response from a remote API endpoint.

Server-side Rendering (SSR)

One of the most often utilized rendering methods is SSR. It's almost the polar opposite of client-side rendering (CSR).

Rendering is handled by the server in the SSR approach. The user sends a request to the server, which processes the HTML, CSS, and JavaScript on the fly and returns a fully loaded page to the user's browser.

The rendering process is repeated every time the user takes action to visit a different page, unlike Client-Side Rendering. Every time, the server will serve the page on demand. Every new page and each request causes the browser to send a request to the server.

The disadvantage of SSR is that it consumes a lot of resources and delays the delivery of content to the user. When opposed to single-paged applications, it takes longer for the page to load. This is due to the fact that the server must render the dynamic material multiple times. The material on the CSR is static and appears almost instantly when the page is reloaded.

Connection issues may occur when your website has a large number of visitors. This occurs when there are too many people attempting to access the resources, and your backend server's computer power is insufficient to handle all of the requests.

Everything delivered to the browser in this method comes from a server. The server is in charge of retrieving web content, processing it, and displaying it in the browser. Server-Side Rendering refers to the processing that occurs on the server every time a request is sent.

Now consider the following SSR example:

export async function getServerSideProps() {
	const res = await fetch('https://contently.com/posts');
	const posts = await res.json();
	return {
		props: {
			data: posts
		}
	};
}

Only the function's name has changed. Another significant distinction is that the function is now called on every request rather than just at build time.

Incremental Static Regeneration in Next.js

Incremental Static Regeneration (ISR) is a new feature that allows you to regenerate static pages while they're running. It's a mix of SSG and SSR.

After you've established your website, you may use Next.js to build or update static pages. Instead of needing to rewrite the entire website, ISR allows developers and content editors to use static generation on a per-page basis. You can keep the advantages of static while growing to millions of pages with ISR.

With ISR, static pages can be created at runtime (on-demand) rather than at build time. You have the ability to create your own build time tradeoffs using analytics, A/B testing, or other data.

On the first request, the page is produced. Unlike SSR, where the visitor must wait for data to be retrieved, a fallback page is served right away.

We can show placeholders and a skeleton page during the fallback stage till everything is fixed. Skeleton pages are a popular design style that can be seen practically anywhere.

Following the resolution of the data, the completed page is cached, and subsequent visitors will receive the cached version immediately, just as with SSG. We can also specify when Next.js should validate and refresh the page.

Even if the visitor revalidates, the visitor receives the cached version first, followed by the updated version. "Stale-while-revalidate" is the usual name for this caching approach. Of course, it was feasible before ISR, but ISR democratized and made this skill more accessible.

Changing your SSR pages to ISR can boost your application's performance and raise your Lighthouse score by tens of points, while also providing a faster experience for your visitors.

Using ISR is similar to using SSG, but with the addition of the revalidate property. This new property specifies how frequently the page should be revalidated (in seconds):

export async function getStaticProps() {
	const res = await fetch('https://contently.com/posts');
	const posts = await res.json();
	return {
		props: {
			data: posts
		},
		revalidate: 60
	};
}

This is how straightforward it is. Nothing out of the ordinary.

It's as simple as using React Hooks to detect fallback mode. This data is stored by the Next.js router. All we have to do now is grab the router and extract the following information:

const { isFallback } = useRouter();

isFallback is a Boolean value that changes when the fallback mode is changed. You can use this snippet in any component you like.

How does Incremental Static Regeneration Work?

When you enable ISR on a website, you're deploying a (largely) static site. You have pre-made static pages, and you have routes in your application that aren't built until your visitors arrive at those pages.

Your users will typically have to wait for a server-side rendered (SSR) page that is one of these unbuilt pages to be built and served all at once. In the case of ISR, however, if your users go along that path, they will be sent to a fallback page. A fallback page serves as a placeholder for the page's actual content, and you can use skeleton components while the data is generated and loaded.

Once that data has been resolved, the page is cached, added to the remainder of the website's bundle, and the built page is displayed to the next user of your website. If the data needs to be updated, the visitor will see the cached version rather than the fallback, and the website can establish a revalidate timetable to revalidate and update data on a regular basis when your users visit the page.

Each of the new blocks in this diagram represents a new page that is created and added to the "stack" at runtime.

The "stale-while-revalidate" caching mechanism is used in this method of providing websites. It's incredibly fast because you can receive almost all of the speed benefits of a pure static page, but with the added bonus of new dynamic data, much like with SSR. Because it blends the best of both worlds, this technique is commonly referred to as "hybrid" development.

There are a few faults in ISR that you should think about before committing to the concept.

When someone visits your page, you want them to view the most recent version right away. The first visitor to a page will not see that with ISR. They'll always look for a backup plan first. If the data becomes stale later, the first visitor to that cached page will view the out-of-date data before it is revalidated. If your users experience unpleasant side-effects as a result of old/unbuilt pages, this uneven experience might be tough to debug.

Rollbacks are no longer instant when you add further pages to your bundle, and you no longer have that single new version of your website when you alter your content.

Assume you create a website with a number of products for sale, each of which is represented by an ISR-ed page. Your users should be able to navigate to a product's website, see a product for sale, and buy it in an ideal case. It will be seen by the next users that visit the website, and the page may change to display that the product is out of stock.

Because your page is cached separately from the bundle, it may exist in a different state for your user than planned if you revert your website to a different deployment. It might be an older version of the website, a newer version, or a weird cached version in the middle trying to revalidate itself. Unfortunately, troubleshooting this is tough because different users may see different pages, making it difficult to duplicate.

Notice how the pages that are cached separately remain with their big checkmarks in this diagram, however, the rolled-back page is no longer the shipped deploy. Users who go to those cached routes may see out-of-date information.

These gotchas are caused by the "stale-while-revalidate" caching that underpins ISR. We end up with a very huge footgun when ISR is built on sending stale content like this, which is confusing for users and irritating for developers.

When to Use Incremental Static Regeneration?

Before you start using ISR, there are a few things to think about. It's effective, but be sure it's appropriate for your situation.

  • Increase API calls
    It's crucial to consider how many API calls ISR could generate. If you set the revalidate property to 5 seconds, your API endpoint will be called every 5 seconds. Depending on API quotas, pricing, and capacity, this might be worth exploring.
  • Stale Data for ISR Initiator
    I'd want to emphasize that the first individual that visits your website and starts ISR will continue to receive the old, stale data. The content will be updated for the second person that visits.
  • Not Beneficial If You Already have Quick Build Time
    Build times may not be as important if your application takes simply a few minutes or fewer to develop. Performing a full build ensures that your new content appears on every page.

Examples of Incremental Static Regeneration

E-commerce, marketing pages, blog posts, ad-supported media, and other applications benefit from incremental static regeneration.

  • Demo of E-commerce
    Next.js Commerce is a one-stop-shop for creating high-performing e-commerce sites.
  • Demo of GitHub Reactions
    React to the original GitHub issue and keep an eye on ISR to see if the statically created landing page has been updated.
  • Demo of Static Tweets
    This project takes 30 seconds to set up, yet it can generate 500 million tweets on-demand using ISR.

ISR: It's More Than Just Caching

ISR is built to keep your generated pages in sync between deployments. This implies you can backtrack at any time without losing your previously generated pages.

Each deployment is identified by an ID, which is used by Vercel and Next.js to save statically created pages. Vercel will update the key to point to the prior deployment when you roll back, allowing for atomic deployments. As a result, you may go back to your previous immutable deployments and they'll still work.

Conclusion

In most real-world applications, though, you'll likely use a combination of static regeneration, client-side rendering, and server-side rendering. Despite the numerous advantages of incremental static regeneration, it is not a substitute for CSR and SSR, and there are numerous scenarios in which you would want to employ those or a combination of the three techniques.

Next.js is used by developers and large teams because of its hybrid approach and ability to incrementally build pages on demand. ISR combines the advantages of static rendering with the flexibility of server rendering. ISR is ready to use right away with the next start.

Next.js was created with slow adoption in mind. You may keep your old code and add as much React as you need with Next.js. By starting small and gradually adding more pages, you can avoid a total rewrite and keep feature development on track.


Monitor Your Websites with Atatus

Atatus keeps track of your web applications to give you a complete picture of your clients' end-user experience. You can determine the source of delayed load times, route changes, and other issues by identifying frontend performance bottlenecks for each page request.

To make bug fixing easier, every JavaScript error is captured with a full stack trace and the specific line of source code marked. To assist you in resolving the JavaScript error, look at the user activities, console logs, and all JavaScript events that occurred at the moment. Error and exception alerts can be sent by email, Slack, PagerDuty, or webhooks.

Try Atatus’s entire features free for 14 days.

Janani
Janani works for Atatus as a Content Writer. She's devoted to assisting customers in getting the most out of application performance management (APM) tools.
India

Monitor your entire software stack

Gain end-to-end visibility of every business transaction and see how each layer of your software stack affects your customer experience.