1
00:00:03,000 --> 00:00:06,413
We've seen how background revalidation works.

2
00:00:06,413 --> 00:00:09,630
Whether you set "revalidate" at the page level,

3
00:00:09,630 --> 00:00:11,717
or on each "fetch" request,

4
00:00:11,717 --> 00:00:14,563
it's always based on a time interval.

5
00:00:14,563 --> 00:00:17,208
That's good enough for many applications,

6
00:00:17,208 --> 00:00:20,038
but it does have some downsides as well.

7
00:00:20,038 --> 00:00:23,244
It means that when we make a change in the CMS

8
00:00:23,244 --> 00:00:26,229
our website will not update immediately,

9
00:00:26,229 --> 00:00:29,068
but only after a few seconds or minutes,

10
00:00:29,068 --> 00:00:31,688
depending on the "revalidate" setting.

11
00:00:31,688 --> 00:00:34,075
And this makes it a bit more difficult

12
00:00:34,075 --> 00:00:37,783
to check that your website has updated correctly.

13
00:00:37,783 --> 00:00:40,678
Also, different pages may be updated

14
00:00:40,678 --> 00:00:42,930
at slightly different times,

15
00:00:43,010 --> 00:00:44,839
because even if you set the

16
00:00:44,839 --> 00:00:46,667
same interval on all pages,

17
00:00:46,735 --> 00:00:48,874
each page is only generated

18
00:00:48,874 --> 00:00:50,934
when a client requests it,

19
00:00:51,013 --> 00:00:55,296
so different pages can expire at different times.

20
00:00:55,296 --> 00:00:58,026
And finally, the server will regenerate

21
00:00:58,026 --> 00:00:59,566
each page periodically

22
00:00:59,636 --> 00:01:01,607
even if the data in the CMS

23
00:01:01,607 --> 00:01:03,359
hasn't actually changed.

24
00:01:03,432 --> 00:01:06,193
So, is there a better option than

25
00:01:06,193 --> 00:01:08,202
time-based revalidation?

26
00:01:08,285 --> 00:01:11,479
Next.js does support another approach,

27
00:01:11,479 --> 00:01:14,207
called "On-demand Revalidation".

28
00:01:14,207 --> 00:01:17,351
This allows us to explicitly control

29
00:01:17,351 --> 00:01:20,058
when Next.js updates the pages.

30
00:01:20,146 --> 00:01:22,377
We can either revalidate a path,

31
00:01:22,377 --> 00:01:25,569
or assign a tag to each "fetch" call,

32
00:01:25,569 --> 00:01:28,548
and then revalidate all the requests

33
00:01:28,548 --> 00:01:30,451
labelled with that tag.

34
00:01:30,533 --> 00:01:32,613
In our example we'll use the

35
00:01:32,613 --> 00:01:34,469
"revalidateTag" function.

36
00:01:34,544 --> 00:01:37,846
Note that this approach requires our application

37
00:01:37,846 --> 00:01:41,761
to somehow be notified when the data changes.

38
00:01:41,761 --> 00:01:45,500
This is usually done by exposing an API route,

39
00:01:45,500 --> 00:01:47,776
that's something we haven't seen yet.

40
00:01:47,776 --> 00:01:50,248
So in this video I'll explain

41
00:01:50,248 --> 00:01:52,037
Route Handlers first,

42
00:01:52,122 --> 00:01:54,405
and then in the next lecture we'll

43
00:01:54,405 --> 00:01:56,151
come back to Revalidation.

44
00:01:56,218 --> 00:01:59,539
Now, what is a Route Handler exactly?

45
00:01:59,539 --> 00:02:03,131
It's a way to provide a URL in our application

46
00:02:03,131 --> 00:02:05,738
that doesn't return a web page,

47
00:02:05,738 --> 00:02:07,840
that is an HTML document,

48
00:02:07,924 --> 00:02:11,050
but instead can return any response,

49
00:02:11,050 --> 00:02:13,397
like JSON data for example.

50
00:02:13,484 --> 00:02:17,131
And can also handle different HTTP methods,

51
00:02:17,131 --> 00:02:21,428
not just GET, but also POST, PUT, and so on.

52
00:02:21,428 --> 00:02:24,279
Let's go and start with a simple example.

53
00:02:24,279 --> 00:02:27,075
We know that we can create new page

54
00:02:27,075 --> 00:02:29,551
routes inside the "app" folder.

55
00:02:29,631 --> 00:02:32,404
An API route works in a similar way:

56
00:02:32,404 --> 00:02:34,955
first we need to create a folder

57
00:02:34,955 --> 00:02:37,027
that matches the URL path.

58
00:02:37,107 --> 00:02:39,524
Now, with the old Pages Router

59
00:02:39,524 --> 00:02:43,474
all API routes were inside the "api" folder.

60
00:02:43,474 --> 00:02:45,613
But with the App Router we can

61
00:02:45,613 --> 00:02:47,323
choose any path we like.

62
00:02:47,395 --> 00:02:50,056
Let's say we want to return some information

63
00:02:50,056 --> 00:02:51,871
about the "health" of our app.

64
00:02:51,932 --> 00:02:54,245
This could be useful to monitor

65
00:02:54,245 --> 00:02:56,186
the status of our website.

66
00:02:56,260 --> 00:02:59,674
Now, instead of creating a "page.jsx",

67
00:02:59,674 --> 00:03:03,311
in this case we want a "route.js" file.

68
00:03:03,311 --> 00:03:05,986
And here we can write code that

69
00:03:05,986 --> 00:03:08,145
handles any HTTP request.

70
00:03:08,231 --> 00:03:11,004
To do that we need to export a function

71
00:03:11,004 --> 00:03:14,504
for each HTTP method we want to support.

72
00:03:14,504 --> 00:03:17,567
Let's start by handling "GET" requests.

73
00:03:17,567 --> 00:03:21,059
Note that "GET" must be written all uppercase.

74
00:03:21,059 --> 00:03:22,892
Let's say we want to return

75
00:03:22,892 --> 00:03:24,454
a simple JSON response,

76
00:03:24,522 --> 00:03:26,975
that tells us if our app is working.

77
00:03:26,975 --> 00:03:30,370
We can use the "NextResponse" object for that,

78
00:03:30,370 --> 00:03:33,915
that we can import from the "next/server" module.

79
00:03:33,915 --> 00:03:36,202
This provides a "json" method,

80
00:03:36,202 --> 00:03:39,125
that will serialize any value we pass.

81
00:03:39,125 --> 00:03:42,002
Let's return an object, with a "healthy"

82
00:03:42,002 --> 00:03:43,513
property set to true,

83
00:03:43,585 --> 00:03:46,418
meaning that our app is working normally.

84
00:03:46,418 --> 00:03:49,989
And that's it. This is a valid route handler.

85
00:03:49,989 --> 00:03:52,765
Let me go and start the dev server,

86
00:03:52,849 --> 00:03:55,420
so we can then test our new route.

87
00:03:55,460 --> 00:03:57,719
If we open the "/health" path

88
00:03:57,719 --> 00:04:01,530
rather than a web page we just see some JSON data.

89
00:04:01,530 --> 00:04:04,026
Now, this path is not meant to

90
00:04:04,026 --> 00:04:06,272
be viewed by regular users,

91
00:04:06,355 --> 00:04:09,022
but it could be called from an automated

92
00:04:09,022 --> 00:04:11,089
monitoring service for example.

93
00:04:11,155 --> 00:04:13,380
There are services that can check

94
00:04:13,380 --> 00:04:15,469
your website like every minute,

95
00:04:15,537 --> 00:04:18,201
and send you a notification if it's down.

96
00:04:18,201 --> 00:04:20,327
Now, this was a very simple

97
00:04:20,327 --> 00:04:22,218
example of an API route.

98
00:04:22,297 --> 00:04:24,874
But why do we need route handlers

99
00:04:24,874 --> 00:04:26,202
for Revalidation?

100
00:04:26,280 --> 00:04:29,237
That's because Strapi can notify our app

101
00:04:29,237 --> 00:04:32,523
whenever some data in the CMS is modified.

102
00:04:32,523 --> 00:04:34,820
And it does that using Webhooks,

103
00:04:34,820 --> 00:04:37,222
which means it can send an HTTP

104
00:04:37,222 --> 00:04:39,314
request to our Next.js app,

105
00:04:39,391 --> 00:04:42,226
posting some JSON data with information

106
00:04:42,226 --> 00:04:43,753
about what's changed.

107
00:04:43,826 --> 00:04:46,423
This example shows the notification

108
00:04:46,423 --> 00:04:48,873
sent when a new entry is created.

109
00:04:48,947 --> 00:04:52,698
So in our Next.js app we need a route handler

110
00:04:52,698 --> 00:04:55,906
that Strapi can call to send this data.

111
00:04:55,906 --> 00:04:59,250
Let's see how to set up a webhook in the CMS.

112
00:04:59,250 --> 00:05:00,857
If we go to Settings,

113
00:05:01,164 --> 00:05:03,468
here we can find the Webhooks.

114
00:05:03,468 --> 00:05:05,425
Let's go and create a new one.

115
00:05:05,425 --> 00:05:07,026
We need to give it a name.

116
00:05:07,026 --> 00:05:09,793
Let's call it "Next App" for example.

117
00:05:09,793 --> 00:05:12,270
The name doesn't really matter, it's

118
00:05:12,270 --> 00:05:14,266
just to identify the webhook.

119
00:05:14,335 --> 00:05:17,843
What's more important is which "Url" to call.

120
00:05:17,843 --> 00:05:20,923
We want to notify our Next.js application,

121
00:05:20,923 --> 00:05:24,462
so the address must be at "localhost:3000",

122
00:05:24,462 --> 00:05:26,985
but we'll want to create a new route for this,

123
00:05:26,985 --> 00:05:30,180
let's call it "webhooks/cms-event".

124
00:05:30,180 --> 00:05:32,609
We can optionally set some Headers.

125
00:05:32,609 --> 00:05:35,848
This can be useful to pass some Authorization

126
00:05:35,848 --> 00:05:37,143
value for example,

127
00:05:37,215 --> 00:05:40,980
so that in the Next.js handler we can then verify

128
00:05:40,980 --> 00:05:43,541
if the request came from Strapi.

129
00:05:43,541 --> 00:05:45,812
But I won't do that right now, to

130
00:05:45,812 --> 00:05:47,120
keep things simple.

131
00:05:47,189 --> 00:05:50,193
What we need to do is select which events

132
00:05:50,193 --> 00:05:52,245
will trigger a notification.

133
00:05:52,319 --> 00:05:55,890
For our example we can select all Entry events.

134
00:05:55,890 --> 00:05:59,787
So we'll be notified whenever an entry is created,

135
00:05:59,787 --> 00:06:01,268
updated, and so on.

136
00:06:01,346 --> 00:06:04,113
Now, let's to Save this new webhook.

137
00:06:04,113 --> 00:06:05,721
And at this point we need to

138
00:06:05,721 --> 00:06:07,099
make this path available

139
00:06:07,157 --> 00:06:09,014
in our Next.js app.

140
00:06:09,014 --> 00:06:12,124
So let's create new folders under "app",

141
00:06:12,124 --> 00:06:14,873
matching the path we configured in Strapi.

142
00:06:14,873 --> 00:06:17,943
And inside there we want a route handler.

143
00:06:17,943 --> 00:06:22,110
What I'll do is move our existing route.js file.

144
00:06:22,110 --> 00:06:23,925
Because we don't really need

145
00:06:23,925 --> 00:06:25,740
a "health" route in our app.

146
00:06:25,804 --> 00:06:28,106
It was just an example, to start

147
00:06:28,106 --> 00:06:29,689
with something simple.

148
00:06:29,761 --> 00:06:33,862
Now, Strapi will send POST requests, not GET,

149
00:06:33,862 --> 00:06:35,893
so we need to change the function

150
00:06:35,893 --> 00:06:36,939
name accordingly.

151
00:06:37,001 --> 00:06:39,030
And we'll receive the "request"

152
00:06:39,030 --> 00:06:40,470
object as an argument.

153
00:06:40,535 --> 00:06:43,891
Let me show you the Next.js documentation again.

154
00:06:43,891 --> 00:06:47,608
Route handlers receive a NextRequest object,

155
00:06:47,608 --> 00:06:50,744
that extends the standard Request interface,

156
00:06:50,744 --> 00:06:53,410
as defined by the Fetch API.

157
00:06:53,410 --> 00:06:55,741
A Request provides some methods,

158
00:06:55,741 --> 00:06:59,997
including "json" that returns the body as JSON,

159
00:06:59,997 --> 00:07:01,714
but wrapped in a Promise.

160
00:07:01,714 --> 00:07:04,590
So, if we declare this function as "async",

161
00:07:04,590 --> 00:07:07,185
we can then get the Strapi "payload"

162
00:07:07,185 --> 00:07:09,977
by awaiting the Promise returned

163
00:07:09,977 --> 00:07:11,722
by "request.json()".

164
00:07:11,809 --> 00:07:14,273
Let's start by logging this value,

165
00:07:14,589 --> 00:07:16,971
so we can see exactly what data

166
00:07:16,971 --> 00:07:18,815
we receive from the CMS.

167
00:07:18,891 --> 00:07:21,400
Now, in this case we don't really

168
00:07:21,400 --> 00:07:23,605
need to return any JSON data,

169
00:07:23,681 --> 00:07:25,540
or any data at all.

170
00:07:25,540 --> 00:07:29,274
But we do need to return at least a success code.

171
00:07:29,274 --> 00:07:31,983
We can create a new "Response" instance.

172
00:07:31,983 --> 00:07:34,945
And note that Response is available globally,

173
00:07:34,945 --> 00:07:38,287
because it's part of the standard Fetch API.

174
00:07:38,287 --> 00:07:41,118
Anyway, as the "body" we can pass "null",

175
00:07:41,118 --> 00:07:43,705
if we don't want to return any data.

176
00:07:43,705 --> 00:07:46,368
But then we can set the "status" code

177
00:07:46,368 --> 00:07:49,529
to 204, that means "No Content"

178
00:07:49,529 --> 00:07:51,670
in the HTTP standard.

179
00:07:51,772 --> 00:07:54,172
It's still a successful response,

180
00:07:54,172 --> 00:07:56,173
that will tell Strapi that we

181
00:07:56,173 --> 00:07:57,829
did process the request.

182
00:07:57,898 --> 00:08:00,853
Now, let's test this POST handler.

183
00:08:00,853 --> 00:08:03,341
Let me clear the server logs first.

184
00:08:03,341 --> 00:08:05,667
And then, if we go back to Strapi,

185
00:08:05,667 --> 00:08:08,200
from this page we can test a webhook

186
00:08:08,200 --> 00:08:10,979
simply by pressing the Trigger button.

187
00:08:10,979 --> 00:08:13,306
You can see that it shows "Success!",

188
00:08:13,306 --> 00:08:15,131
which means it should have called

189
00:08:15,131 --> 00:08:16,293
our app successfully.

190
00:08:16,348 --> 00:08:18,742
And in fact we can see the "payload"

191
00:08:18,742 --> 00:08:20,006
object in the logs.

192
00:08:20,072 --> 00:08:22,535
It contains an "event" property,

193
00:08:22,535 --> 00:08:24,668
that's set to "trigger-test"

194
00:08:24,668 --> 00:08:26,345
for this notification.

195
00:08:26,421 --> 00:08:29,966
But this proves that our Route Handler is working,

196
00:08:29,966 --> 00:08:33,205
and the Strapi webhook is configured correctly.

197
00:08:33,205 --> 00:08:36,006
In the next video we'll see how to handle

198
00:08:36,006 --> 00:08:38,648
real changes to the CMS data,

199
00:08:38,648 --> 00:08:41,876
and how to perform on-demand revalidation.

