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
Move to your app folder and run
npm run dev
Visiting http://localhost:3000 you should see the following:
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:
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
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')
}
}
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
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
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)
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?You can code api handler, let say
pages/system/revalidate
which can receive parameter likepageUrl
. Then in the next.config.js, you can have a rewrite rule like thisSo 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.for me, on Vercel, the revalidate works on all route expect the root '/'. It raises error 500. what should I do?
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.