We've seen how background revalidation works.
Whether you set "revalidate" at the page level,
or on each "fetch" request,
it's always based on a time interval.
That's good enough for many applications,
but it does have some downsides as well.
It means that when we make a change in the CMS
our website will not update immediately,
but only after a few seconds or minutes,
depending on the "revalidate" setting.
And this makes it a bit more difficult
to check that your website has updated correctly.
Also, different pages may be updated
at slightly different times,
because even if you set the
same interval on all pages,
each page is only generated
when a client requests it,
so different pages can expire at different times.
And finally, the server will regenerate
each page periodically
even if the data in the CMS
hasn't actually changed.
So, is there a better option than
time-based revalidation?
Next.js does support another approach,
called "On-demand Revalidation".
This allows us to explicitly control
when Next.js updates the pages.
We can either revalidate a path,
or assign a tag to each "fetch" call,
and then revalidate all the requests
labelled with that tag.
In our example we'll use the
"revalidateTag" function.
Note that this approach requires our application
to somehow be notified when the data changes.
This is usually done by exposing an API route,
that's something we haven't seen yet.
So in this video I'll explain
Route Handlers first,
and then in the next lecture we'll
come back to Revalidation.
Now, what is a Route Handler exactly?
It's a way to provide a URL in our application
that doesn't return a web page,
that is an HTML document,
but instead can return any response,
like JSON data for example.
And can also handle different HTTP methods,
not just GET, but also POST, PUT, and so on.
Let's go and start with a simple example.
We know that we can create new page
routes inside the "app" folder.
An API route works in a similar way:
first we need to create a folder
that matches the URL path.
Now, with the old Pages Router
all API routes were inside the "api" folder.
But with the App Router we can
choose any path we like.
Let's say we want to return some information
about the "health" of our app.
This could be useful to monitor
the status of our website.
Now, instead of creating a "page.jsx",
in this case we want a "route.js" file.
And here we can write code that
handles any HTTP request.
To do that we need to export a function
for each HTTP method we want to support.
Let's start by handling "GET" requests.
Note that "GET" must be written all uppercase.
Let's say we want to return
a simple JSON response,
that tells us if our app is working.
We can use the "NextResponse" object for that,
that we can import from the "next/server" module.
This provides a "json" method,
that will serialize any value we pass.
Let's return an object, with a "healthy"
property set to true,
meaning that our app is working normally.
And that's it. This is a valid route handler.
Let me go and start the dev server,
so we can then test our new route.
If we open the "/health" path
rather than a web page we just see some JSON data.
Now, this path is not meant to
be viewed by regular users,
but it could be called from an automated
monitoring service for example.
There are services that can check
your website like every minute,
and send you a notification if it's down.
Now, this was a very simple
example of an API route.
But why do we need route handlers
for Revalidation?
That's because Strapi can notify our app
whenever some data in the CMS is modified.
And it does that using Webhooks,
which means it can send an HTTP
request to our Next.js app,
posting some JSON data with information
about what's changed.
This example shows the notification
sent when a new entry is created.
So in our Next.js app we need a route handler
that Strapi can call to send this data.
Let's see how to set up a webhook in the CMS.
If we go to Settings,
here we can find the Webhooks.
Let's go and create a new one.
We need to give it a name.
Let's call it "Next App" for example.
The name doesn't really matter, it's
just to identify the webhook.
What's more important is which "Url" to call.
We want to notify our Next.js application,
so the address must be at "localhost:3000",
but we'll want to create a new route for this,
let's call it "webhooks/cms-event".
We can optionally set some Headers.
This can be useful to pass some Authorization
value for example,
so that in the Next.js handler we can then verify
if the request came from Strapi.
But I won't do that right now, to
keep things simple.
What we need to do is select which events
will trigger a notification.
For our example we can select all Entry events.
So we'll be notified whenever an entry is created,
updated, and so on.
Now, let's to Save this new webhook.
And at this point we need to
make this path available
in our Next.js app.
So let's create new folders under "app",
matching the path we configured in Strapi.
And inside there we want a route handler.
What I'll do is move our existing route.js file.
Because we don't really need
a "health" route in our app.
It was just an example, to start
with something simple.
Now, Strapi will send POST requests, not GET,
so we need to change the function
name accordingly.
And we'll receive the "request"
object as an argument.
Let me show you the Next.js documentation again.
Route handlers receive a NextRequest object,
that extends the standard Request interface,
as defined by the Fetch API.
A Request provides some methods,
including "json" that returns the body as JSON,
but wrapped in a Promise.
So, if we declare this function as "async",
we can then get the Strapi "payload"
by awaiting the Promise returned
by "request.json()".
Let's start by logging this value,
so we can see exactly what data
we receive from the CMS.
Now, in this case we don't really
need to return any JSON data,
or any data at all.
But we do need to return at least a success code.
We can create a new "Response" instance.
And note that Response is available globally,
because it's part of the standard Fetch API.
Anyway, as the "body" we can pass "null",
if we don't want to return any data.
But then we can set the "status" code
to 204, that means "No Content"
in the HTTP standard.
It's still a successful response,
that will tell Strapi that we
did process the request.
Now, let's test this POST handler.
Let me clear the server logs first.
And then, if we go back to Strapi,
from this page we can test a webhook
simply by pressing the Trigger button.
You can see that it shows "Success!",
which means it should have called
our app successfully.
And in fact we can see the "payload"
object in the logs.
It contains an "event" property,
that's set to "trigger-test"
for this notification.
But this proves that our Route Handler is working,
and the Strapi webhook is configured correctly.
In the next video we'll see how to handle
real changes to the CMS data,
and how to perform on-demand revalidation.