DEV Community

Cover image for Next.js on-demand revalidation is here! ๐Ÿš€
pul
pul

Posted on • Edited on

Next.js on-demand revalidation is here! ๐Ÿš€

Next.js on-demand static regeneration is finally here! ๐Ÿ˜

This is a super cool feature that makes possible to refresh statically generate pages.

Think about an heandless cms with a product catalog. With this option you can statically generate your catalog pages and โ€œinvalidateโ€ the cache programmatically when the user edit the content.

In this article Iโ€™ll just try the new API (still in beta) with a little next app, nothing more of what you can find in the documentation so feel free to skip it and take a look directly at the nextjs docs.

Keep reading if you want to have a minimal example. Here you can find a repo with the code.

Setup

npx create-next-app@latestnpx
Enter fullscreen mode Exit fullscreen mode

Move to your app folder and run

npm run dev
Enter fullscreen mode Exit fullscreen mode

Visiting http://localhost:3000 you should see the following:

Nextjs starter page

Now you are ready to start.

We are going to build a very basic app that shows a timestamp, a button that triggers the revalidate api and a link that refresh the page.

Basically the following:

Next.js on-demand revalidation demo pulbasso

For this quick example itโ€™s fine to call the revalidate api from the client but in a real world application the logic should be triggered from a trusted backend since you should use a secret token to authorize the request.

The timestamp is generated at build time and if you keep refreshing the page you should see always the same value until you click the โ€œRevalidateโ€ button, then at the next refresh you should see a new value.

Code it

We can replace the code in the index.js class adding the getStaticProps method in order to generate the timestamp. Here is the code:

import {useState} from "react";

function Home({ timestamp }) {

  const [result, setResult] = useState("");

  const revalidate = async () => {
    await fetch("/api/revalidate?secret=supersecret");
    setResult("Done. Try to refresh the page");
  }

  return (
    <div className="root">
      <div className="timestamp">{timestamp}</div>
      <div>{result}</div>
      <div className="actions">
        <button onClick={() => { revalidate()}}>Revalidate</button>
        <a href="">Refresh</a>
      </div>

    </div>
  );
}

// This function gets called at build time
export async function getStaticProps() {
  return {
    props: {
      timestamp: new Date().toISOString()
    },
  }
}

export default Home
Enter fullscreen mode Exit fullscreen mode

The revalidate logic is in the revalidate function under the api folder:

// pages/api/revalidate.js

export default async function handler(req, res) {
    // Check for secret to confirm this is a valid request
    if (req.query.secret !== process.env.MY_SECRET_TOKEN) {
      return res.status(401).json({ message: 'Invalid token' })
    }

    try {
      await res.unstable_revalidate('/')
      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')
    }
  }
Enter fullscreen mode Exit fullscreen mode

In order to revalidate the page you just need to provide the path of the page you want to reload.

As you can see from the code above you have to include a secret token to call the api.

This token is provided in the request (thatโ€™s why is not a good idea to call the revalidate from the client side ๐Ÿ˜…) and should match with the one configured as environment variable

We can add the token variable to a .env.local file next will read it at start time (More options here)

MY_SECRET_TOKEN=supersecret
Enter fullscreen mode Exit fullscreen mode

Run it

In order to see the result you have to make a production build and serve the app using the following:

npm run build && npm run start
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this quick post we saw how to use the new on-demand revalidate feature of Next.js 12.1.

Itโ€™s a very simple api and I think there are many use cases, I canโ€™t wait the stable release to use it in my projects!! ๐Ÿš€

Top comments (4)

Collapse
 
danihengeveld profile image
Dani Hengeveld

Is there a way to revalidate multiple pages? Or all pages? Or would you just have to call .unstable_revalidate() multiple times with different paths?

Collapse
 
letanthanhtai profile image
Le Tan Thanh Tai

You can code api handler, let say pages/system/revalidate which can receive parameter like pageUrl. Then in the next.config.js, you can have a rewrite rule like this

{
          source: '/:refreshPage(.+?)/revalidate/',
          destination: '/api/system/revalidate?pageUrl=:refreshPage',
        }
Enter fullscreen mode Exit fullscreen mode

So now, on any page, if you call /hello/revalidate, it will revalidate your hello page :). If you want to revalidate multiple pages, you can have another page which do a batch revalidate or just a bunch of curl scripts to do it.

Collapse
 
behzadha profile image
Behzad Haji Ahmadi

for me, on Vercel, the revalidate works on all route expect the root '/'. It raises error 500. what should I do?

Collapse
 
ositoozy profile image
Oscar Lodriguez

For me as well if I call it from the server side. But use it in a useEffect or client side context it won't fail.