We're currently using dynamic rendering
to make sure our pages display
the latest data from the CMS.
But the downside of this approach is that
the server regenerates each page
every time it's requested,
even though the data in the CMS
doesn't change very often.
For this reason Next.js provides
a feature called "revalidation",
that lets us generate static pages,
but then "revalidate" them at runtime,
which effectively means regenerate them.
Let's start with "Background Revalidation",
which regenerates the pages
at a specific interval,
like every 60 seconds in this example.
We can configure this in our page file,
by exporting a property called "revalidate".
Or we can also enable it when calling "fetch",
but we'll cover that in the next video.
Let's start by configuring it at the page level.
Now, let's assume that
we only want to be able to publish new reviews,
we don't really plan to modify existing content.
If that's the case, then we
only need to revalidate
the Home and Reviews pages.
Because that's where we show
the most recent entries,
and we want them to load fresh data
to include the new review.
As for the individual ReviewPage,
we've seen at the start of this section that
Next.js can generate a new
review page automatically,
if we simply use the default
"dynamicParams" behavior.
We just need to remove "force-dynamic"
from this page.
So, for this video I'll make this assumption:
that we only want to publish new reviews,
and not update existing ones.
Let me delete this "cuphead-2" by the way,
that we only created for testing.
We could restrict our collaborators
to only create new reviews
by configuring the Roles in Strapi.
Each user has a role,
like "Editor", that's predefined,
and here you can configure permissions.
So we could let editors Create,
Read, and Publish reviews,
but not Update or Delete them,
so we can be sure nobody will modify
any review after it's published,
and therefore in our Next.js app
we only need to worry about
updating our pages to display new reviews.
Anyway, for our tests we won't
actually use separate users.
We always log in as "admin",
that has all permissions.
Let's go back to our code now.
As I mentioned, if we're only
going to add new reviews,
then in this page we can simply
remove "force-dynamic",
and also re-enable "generateStaticParams".
This way the build will statically
generate all the existing reviews.
But if we publish a new review in the CMS
Next.js will automatically render
the new page on demand,
thanks to the "dynamicParams" feature.
Now, let's think about the HomePage.
We no longer want this to be "dynamic",
but we want it to "revalidate" periodically,
so from time to time Next.js
will regenerate this page
fetching the latest data from the CMS.
The "revalidate" value is a number of seconds.
If we set it to 30 seconds for example,
once it's generated, this page
will be valid for 30 seconds.
If the server receives a request
and finds thatÂ the page is older than 30 seconds
then it will re-render it in the background.
We'll see this in action in a minute.
Now, I'm using a pretty short interval here
just to make it easier to test.
But, in production you may want to set it to
maybe 5 minutes, or at least 1 minute,
so the page will be updated, but not too often.
Anyway, we want to do the
same for the ReviewsPage,
revalidate it every 30 seconds.
So if we add a new entry to the CMS
it will be displayed in this page,
after a short interval.
To test this feature, we need
to do a production build,
because we know that
the dev server always regenerates
each page every time.
Ok. All routes appear to be static
in the build summary.
But that doesn't really tell the full story,
because yes they are static,
but they will also be regenerated periodically.
Let's see exactly how it works.
Let me clear the logs.
All pages have been statically
generated during the build,
so if we load them in the browser
we won't see any "rendering"
messages in the server logs.
But now let's go and add a new review in the CMS.
I'll just duplicate an existing entry,
let's take "Subnautica",
then change it to "subnautica-2",
and Save and Publish the new entry.
At this point, if we go back to our website,
and reload the Reviews page,
it's not showing the new entry yet,
because it's been less than 30 seconds
since this page was generated.
So we need to wait a few seconds,
and then try again.
You can see in the logs that
it rendered the ReviewsPage component,
and the data returned by Strapi
includes the new "subnautica-2" slug.
It then rendered some other pages as well,
because of link prefetching.
However, in the browser we still
don't see "Subnautica 2".
That seems weird.
What's going on here is that
Next.js does "background revalidation".
This means that, if it receives a request
for a page that's no longer valid,
it will regenerate it, but in the background.
It still returns the old page
to the browser first,
so the user doesn't have to wait for the response,
and then it generates the new
page in the background
to have it ready for subsequent requests.
So, if we reload the page again,
this time we do see "Subnautica 2" in the list.
Note that the server didn't render
the ReviewsPage component again.
It simply returned the page it generated
after our previous request.
So, keep this in mind when testing your pages:
the first request that triggers revalidation
still receives the old page,
but it will cause a new page to be generated
and you can see it if you make a second request.
Now, if we go to the Home page,
we can see that this one has been updated as well.
And if we open the new review page,
this also works.
Although this one is not using revalidation,
but simply the default "dynamicParams" behavior.
Now, since we're using a time
interval for revalidation,
the pages will always be regenerated
if they're older than 30 seconds,
no matter whether there is new
data in the CMS or not.
If I keep reloading this page,
at some point the existing version will expire,
and you can see in the server logs that
the component was rendered again.
Even though the data in the CMS hasn't changed,
so the page will look the same as before anyway.
But it still made a fetch request to Strapi,
and regenerated the HTML.
The Next.js app has no way of knowing
if the data in the CMS has changed or not.
After generating the page,
the server will reuse it for at least 30 seconds,
and so on.
I'm saying "at least" 30 seconds because
there isn't a timer that goes off automatically
and regenerates the page after exactly 30 seconds.
The process is driven by client requests.
If nobody loads this page for say 3 hours,
then the server will not regenerate
it during that period.
It's only when a client makes a request that
the server will detect that the
existing page is too old,
and therefore needs to be rerendered.
So, time-based revalidation
is very easy to enable:
you just need to export the "revalidate" property
specifying a time interval in number of seconds.
But it's important to understand how it works.
It's effectively a cache.
Each static page is cached,
and expires after the given interval.