Prismic Meetup

Rebranding: How can it be a turning point for your growth?

Watch ↗

Build Better Next.js Sites with On-demand Incremental Static Regeneration

Written by Angelo Ashmore in A speed gauge for optimization Optimization on February 17, 2022
Next.js

Next.js 12.1 introduced a new feature called “on-demand Incremental Static Regeneration.” It enables you to build better sites using content management systems like Prismic by letting you iterate on your site and its content more quickly.

Using on-demand Incremental Static Regeneration (ISR), you can tell Next.js which pages in your site have changed as a result of content changes. Next.js can automatically rebuild those pages with fresh content while keeping the rest of your pages in its cache.

With this new feature, you can deploy changes quicker, rebuild pages more efficiently, and deliver more up-to-date content to your site’s visitors.

Who should use this new feature?

Developers who build sites using Static Site Generation (SSG) with Next.js’s getStaticProps(). SSG is recommended for sites using content management systems like Prismic since content usually won’t change for each visitor; pages can be built once and reused until their content is edited.

Why should you use it?

It ensures visitors will see your latest content in less time than before. Without the new “on-demand” aspect, sites using standard ISR may show old content while Next.js rebuilds pages. You’ll spend less time waiting on Next.js to rebuild and more time iterating on your site.

Where is it supported?

On-demand ISR works anywhere that supports the Next.js Build API, including Vercel. That currently does not include Netlify, but it may be supported on their platform in the future.

How to use on-demand Incremental Static Regeneration

We can use on-demand ISR by creating a new API endpoint in your app and a webhook in your content management system. We’ll use Prismic to demonstrate this. Each time content is published to Prismic, the API endpoint will be called automatically, which will tell Next.js to rebuild any affected pages.

Step 1: Add an API endpoint with revalidate( )

Create a new API endpoint at pages/api/revalidate.js that uses the new revalidate() function in a Prismic project. (Don't have one? You can start here!) This API endpoint should do the following:

  1. Read the webhook’s data to understand which content was updated.
  2. Determine which pages were affected as a result of those changes.
  3. Rebuild those pages.

Read through the code below to see how this is accomplished for Prismic. It uses the latest versions of the @prismicio/client and @prismicio/helpers packages to query Prismic documents and convert them to page URLs.

 
// pages/api/revalidate.js

import * as prismic from '@prismicio/client'
import * as prismicH from '@prismicio/helpers'

// Import your app's Link Resolver (if your app uses one)
import { linkResolver } from '../prismicio'

/**
 * This API endpoint will be called by a Prismic webhook. The webhook
 * will send an object containing a list of added, updated, or deleted
 * documents. Pages for those documents will be rebuilt.
 *
 * The Prismic webhook must send the correct secret.
 */
export default async function handler(req, res) {
  if (req.body.type === 'api-update' && req.body.documents.length > 0) {
    // Check for secret to confirm this is a valid request
    if (req.body.secret !== process.env.PRISMIC_WEBHOOK_SECRET) {
      return res.status(401).json({ message: 'Invalid token' })
    }

    // If you have a `createClient()` function defined elsewhere in
    // your app, use that instead
    const client = prismic.createClient('your-repo-name')

    // Get a list of URLs for any new, updated, or deleted documents
    const documents = await client.getAllByIDs(req.body.documents)
    const urls = documents.map((doc) => prismicH.asLink(doc, linkResolver))

    try {
      // Revalidate the URLs for those documents
      await Promise.all(
        urls.map(async (url) => await res.revalidate(url))
      )

      return res.json({ revalidated: true })
    } catch (err) {
      // If there was an error, Next.js will continue to show
      // the last successfully generated page
      return res.status(500).send('Error revalidating')
    }
  }

  // If the request's body is unknown, tell the requester
  return res.status(400).json({ message: 'Invalid body' })
}

When this API endpoint is called by Prismic’s webhook, Next.js will rebuild any affected pages — and only those pages — fetching new content in the process. Remember, the rest of your content is still up-to-date!

To ensure only Prismic can trigger page rebuilds, the endpoint checks that the webhook contains a secret value. We'll set that up next.

Step 2: Update your getStaticProps( ) (if needed)

If you are already using ISR, you can remove the revalidate option from your pages' getStaticProps() function (reminder: revalidate is the number of seconds that the page is valid in Next.js’s cache). Because the pages will now be manually revalidated, you can tell Next.js that a built page is good indefinitely until the next revalidate() call.

If you are not already using ISR, good news: you don't have to change anything!

 
  export async function getStaticProps() {
    // Fetch your data here...
  
    return {
      props: {
        // List your props here...
      },
-     revalidate: 60
    }
  }

Step 3: Create a secret

We can configure Prismic's webhook to contain a secret value. By providing the same secret value to both Prismic and your deployed site, we can block unauthorized calls to the API endpoint. You can think of the secret value as a kind of password. We don't want just anyone to come around and call that API endpoint, after all.

Using an environment variable is the safest way to configure a secret in your project. How you set this up will depend on where you deploy your project. If you deploy to Vercel, you can learn how to add an environment variable in their documentation.

In the /api/revalidate.js code above, the environment variable's name is PRISMIC_WEBHOOK_SECRET. Create some kind of string and save it as an environment variable with that name.

We're going to use that secret again when we set up the Prismic webhook.

A cartoon graphics space scene showing an astronaut exploring space as rockets and planets float around.

Stay on the leading edge of development with a monthly coding challenge.

Explore new tech with a fun, scaffolded, coding challenge that lands in your inbox once a month. You'll get all of the learning with minimal spin-up.

Step 4: Create a Prismic webhook

You can configure Prismic to call the on-demand ISR API endpoint any time content is changed using a webhook. Here’s how to set one up:

  1. Open the "Settings" page in your Prismic repository.
  2. Select “Webhooks” in the sidebar and click “Create a webhook.”
  3. Enter the /api/revalidate API endpoint in the "URL" field (this should be the full URL of your production site). Be sure not to use a trailing slash (e.g. /api/revalidate/) as it might stop the webhook from working.
  4. Enter the secret you created for the PRISMIC_WEBHOOK_SECRET environment variable in the "Secret" field.
  5. With everything entered, click “Add this webhook.”

You can learn more about Prismic’s webhooks in our documentation.

That’s it! Deploy your site with the new API endpoint, and Next.js will take care of the rest.

Anytime your content updates are published, Prismic will call your API endpoint to clear cached pages as needed. Next.js will rebuild those pages with your new content automatically.

Prismic ❤️ Next.js

We love Next.js at Prismic. Its developer-centric approach and focus on progressing the web is in line with our philosophy. We’ll continue to integrate new features and share best practices as Next.js grows.

Happy coding! 🚀

Profile picture

Angelo Ashmore

Senior Developer Experience Engineer at Prismic focusing on Gatsby, React, and TypeScript, in no particular order.

More posts