A year ago, support for static Web site generation (SSG) was released in next.js 9.3, making it the first hybrid framework. At this point I was already a happy user of next.js, but this release makes next.js my new default solution. After using next.js extensively, I joined Vercel to help companies like Tripadvisor and The Washington Post adopt and expand next.js.

In this article, I want to explore a new evolution of Jamstack. Incremental static regeneration (ISR). Below you’ll see guidelines for ISR — including use cases, demonstrations, and tradeoffs.

Static site generation issues

The idea behind Jamstack is appealing: pre-rendered static pages can be pushed to a CDN and become globally available in seconds. Static content is fast, resilient to downtime, and instantly indexed by crawlers. But there are some problems.

If you use Jamstack architecture when building a large static site, you can get stuck and wait a few hours for your site to build. If you double the number of pages, you double the build time. Let’s consider Target.com. Is it possible to statically generate millions of products with every deployment?

Even if every page was statically generated in an unrealistic 1 millisecond, rebuilding the entire site would still take hours. For large web applications, the option of _ complete _ static web site generation is not feasible. Larger teams need a more flexible, personalized hybrid solution.

Content Management System (CMS)

For many teams, the content of their site is decouple from the code. Using a headless CMS allows content editors to publish changes without involving developers. However, for traditional static sites, this process can be slow.

Consider an e-commerce store with 100,000 products. Product prices change frequently. When a content editor changed the price of headphones from $100 to $75 as part of a promotion, their CMS used web hooks to rebuild the entire site. It is not feasible to wait several hours to reflect the new price.

Lengthy builds and unnecessary calculations can also incur additional costs. Ideally, your application is smart enough to understand what products have changed and update those pages incrementally without a complete rebuild.

Incremental static regeneration (ISR)

Next.js allows you to create or update static pages _ after _ the site has been created _. Incremental static regeneration (ISR) enables developers and content editors to use static generation on a per-page basis without having to rebuild the entire site. With ISR, you can retain the benefits of static while scaling to millions of pages.

Static pages can be generated at run time (on demand) rather than at build time with ISR. Using analytics, A/B testing, or other metrics, you have the flexibility to make your own trade-offs on build time.

Consider the previous e-commerce store with 100,000 products. In a realistic 50ms scenario of statically generating each product page, this would take nearly 2 hours without ISR. With ISR, we have a choice.

  • Faster builds generate 1,000 of the most popular products at build time. Requests to other products will be a cache miss, generated statically on demand. 1 minute build.
  • A higher cache hit ratio generates 10,000 products at build time, ensuring that more products are cached before the user requests them: an 8-minute build.

Let’s look at an example of AN ISR for an e-commerce product page.

Let’s start

Fetching the data

If you’ve never used next.js before, I recommend reading Next.js Primer to get the basics right. ISR uses the same next.js API to generate static pages. GetStaticProps. By specifying revalidate: 60, we tell Next. Js to use ISR for this page.

  1. Next. Js can define a revalidation time for each page. Let’s set it to 60 seconds.
  2. The initial request for the product page will display a cached page with the original price.
  3. The product data is updated in the CMS.
  4. Any requests to the page after the initial request and before 60 seconds will be cached and effective immediately.
  5. After the 60-second window, the cached (stale) page is still displayed on the next request. Next. Js triggers page regeneration _ in the background.
  6. Once the page is successfully generated, next.js invalidates the cache and displays the updated product page. If the background regeneration fails, the old page will not be changed.
// pages/products/[id].js

export async function getStaticProps({ params }) {
  return {
    props: {
      product: await getProductFromDatabase(params.id)
    },
    revalidate: 60
  }
}
Copy the code

Path is generated

Next.js defines which products are built at build time and which are built on demand. Let’s only generate the 1000 most popular products at build time, providing a list of the top 1000 product ids to getStaticPaths.

We need to configure the “fallback” way for Next. Js to request any other products after the initial build. There are two options to choose from: blocking and true.

  • fallback: blocking(preferred)

    When a request is made to a page that has not yet been generated, next.js will render the page server on the first request. Future requests will provide static files from the cache.
  • fallback: true

    When a request is made to a page that has not yet been generated, next.js will immediately provide a static page with loaded status on the first request. When the data is loaded, the page is re-rendered with new data and cached. Future requests will provide static files from the cache.
// pages/products/[id].js export async function getStaticPaths() { const products = await getTop1000Products() const Paths = products.map((product) => ({params: {id: product.id}})) return {path, fallback: 'blocking'}}Copy the code

Weigh the pros and cons

Next. Js is primarily focused on the end user. The “best solution” is relative and varies by industry, audience, and application nature. Next. Js allows developers to switch between different solutions without leaving the framework, allowing you to pick the right tools for your project.

Server-side rendering

ISR is not always the right solution. For example, Facebook’s news feed can’t show stale content. In this case, you’ll want to use SSR and perhaps your own cache-Control headers, invalidating the content with proxy keys. Since next.js is a hybrid framework, you can make these trade-offs yourself and stay within the framework.

// You can cache SSR pages at the edge using Next.js
// inside both getServerSideProps and API Routes
res.setHeader('Cache-Control', 's-maxage=60, stale-while-revalidate');
Copy the code

SSR and edge caches are similar to ISR (especially in the case of stale-while-revalidate cache headers), with the main difference being the _ first _ request. With ISR, the first request is guaranteed to be static if rendered in advance. Even if your database fails, or you have a problem communicating with your API, your users will still see static pages served correctly. However, SSR will allow you to customize your page based on incoming requests.

Note: Using SSR without caching results in performance degradation. Every millisecond counts when it comes to preventing users from seeing your site, and it can make a big difference to your TTFB (first byte of time).

Static site generation

Isrs don’t always make sense for small sites. If your revalidation period is longer than it takes to rebuild the entire site, you might as well use traditional static site generation.

Client-side rendering

If you use React instead of next.js, you’re using client-side rendering. Your application provides a load state and then requests data in the client’s JavaScript (for example, useEffect). While this does increase your choice of hosts (since you don’t need a server), it comes at a cost.

The lack of pre-rendered content from the initial HTML results in slower search engine optimization (SEO) and less dynamics. It is also impossible to use CSRS with JavaScript disabled.

ISR back option

If your data can be accessed quickly, consider using Fallback: Blocking. Then, you don’t need to worry about the load state, and your page will always show the same results (whether it’s cached or not). If your data retrieval is slow, fallback: true, you can immediately show the loading status to the user.

ISR: It’s not just caching

Although I have explained ISR in the context of caching, it is designed to persist your generated pages across different deployments. This means you can roll back immediately without losing pages you previously generated.

Each deployment can be typed with an ID, which next.js uses to hold statically generated pages. When you roll back, you can update the key to point to the previous deployment, thus achieving atomic deployment. This means that you can access your previous immutable deployments and they will work as planned.

  • Here is an example of recovering code with ISR.
  • You push code and get a deployment ID 123.
  • Your page contains a typo “Smshng Magazine”.
  • You update the page in your CMS. No redeployment is required.
  • Once your page shows “Smashing Magazine”, it will be persisted in storage.
  • You push some bad code and deploy ID 345.
  • You roll back to deployment ID 123.
  • You still see “Smashing Magazine”.

Rolling back and persisting static pages is outside the scope of next.js, depending on your hosting service provider. Note that ISR is different from server restore using cache-Control Headers because by design the Cache expires. They are not shared across regions and will be cleared when restored.

An example of incremental static regeneration

Incremental static regeneration works well for e-commerce, marketing pages, blog posts, ad-supported media, and more.

  • Next. Js Commerce is an all-in-one starter kit for high-performance e-commerce sites.
  • GitHub Response demo Reacts to GitHub’s original problem and watches the ISR update statically generated landing page.
  • Static Tweets demonstrate that the project is deployed in 30 seconds, but 5 million tweets can be statically generated on demand using ISR.

Learn Next. Js today

Developers and large teams choose next.js because of its hybrid approach and ability to incrementally generate pages on demand. With ISR, you get the benefits of static and the flexibility of server rendering. ISR out of the box, Next Start.

Next. Js is designed for gradual adoption. With next.js, you can continue to use your existing code and add as much (or as little) React as you need. By starting small and incrementally adding pages, you can avoid a complete rewrite and prevent feature work from going off the rails. Learn more about next.js — have fun coding!

Further reading

  • Start using next.js
  • Compare Next. Js styling methods
  • How to build GraphQL server using API routing of Next. Js