1
00:00:03,000 --> 00:00:05,682
We've seen how to use Incremental

2
00:00:05,682 --> 00:00:07,308
Static Regeneration,

3
00:00:07,389 --> 00:00:10,176
by setting the "revalidate" option,

4
00:00:10,176 --> 00:00:12,943
which means this page will expire

5
00:00:12,943 --> 00:00:14,958
after a certain timeout,

6
00:00:15,042 --> 00:00:19,218
and therefore be regenerated, fetching new data.

7
00:00:19,218 --> 00:00:23,205
However even this approach has some downsides.

8
00:00:23,205 --> 00:00:26,943
When we modify a product in our CMS, our pages

9
00:00:26,943 --> 00:00:30,194
won't update immediately, but only after

10
00:00:30,194 --> 00:00:32,631
the revalidate period expires.

11
00:00:32,794 --> 00:00:35,790
Also, it's not easy to tell exactly

12
00:00:35,790 --> 00:00:38,186
when a page will be updated,

13
00:00:38,272 --> 00:00:42,118
because it's only when somebody actually requests

14
00:00:42,118 --> 00:00:45,728
that page that Next.js checks if it's expired,

15
00:00:45,728 --> 00:00:47,691
and if so regenerates it.

16
00:00:47,848 --> 00:00:52,121
Now, Next.js 12.2 introduced a new feature called

17
00:00:52,121 --> 00:00:54,650
"on-demand revalidation" that

18
00:00:54,650 --> 00:00:57,180
doesn't have those downsides.

19
00:00:57,354 --> 00:01:01,253
What this allows us to do is to regenerate a page

20
00:01:01,253 --> 00:01:04,595
as soon as we modify some data in the CMS.

21
00:01:04,674 --> 00:01:06,221
Let's take a quick look at

22
00:01:06,221 --> 00:01:07,708
the example on this page.

23
00:01:08,534 --> 00:01:11,829
The way this works is that we can expose

24
00:01:11,829 --> 00:01:14,465
an API route in our Next.js app,

25
00:01:14,548 --> 00:01:16,661
that will be called by our CMS

26
00:01:16,661 --> 00:01:18,704
whenever we update some data.

27
00:01:18,774 --> 00:01:22,352
And in this API handler we can tell Next.js

28
00:01:22,352 --> 00:01:25,264
which page needs to be regenerated,

29
00:01:25,348 --> 00:01:28,921
based on which data was updated in the CMS.

30
00:01:28,921 --> 00:01:31,989
Now, to use this approach, we need a CMS

31
00:01:31,989 --> 00:01:34,673
capable of calling our Next.js app.

32
00:01:34,750 --> 00:01:37,254
Most content management systems will

33
00:01:37,254 --> 00:01:39,201
provide some way to do that.

34
00:01:39,270 --> 00:01:41,774
In Strapi, if we go to Settings,

35
00:01:41,810 --> 00:01:44,543
there is a section called "Webhooks".

36
00:01:44,543 --> 00:01:48,414
A "webhook" is simply a URL we can call to notify

37
00:01:48,414 --> 00:01:51,811
another application when something happens.

38
00:01:51,890 --> 00:01:54,703
Let's go ahead an create a new webhook,

39
00:01:54,703 --> 00:01:56,766
that we can call "Revalidate". The

40
00:01:56,766 --> 00:01:58,525
name is not really important.

41
00:01:58,586 --> 00:02:04,384
As the URL we want to call our Next.js app, that, when running locally,

42
00:02:04,384 --> 00:02:06,507
is at localhost port 3000.

43
00:02:06,589 --> 00:02:09,271
We'll need to create an API route, so

44
00:02:09,271 --> 00:02:11,666
it will be under the "/api" path.

45
00:02:11,738 --> 00:02:14,136
And we can call it "revalidate". Again,

46
00:02:14,136 --> 00:02:15,858
this is an arbitrary choice.

47
00:02:15,919 --> 00:02:18,906
The other thing we need to do is select which

48
00:02:18,906 --> 00:02:21,826
"Events" will trigger a call to the webhook.

49
00:02:21,893 --> 00:02:27,648
If we select "Entry", this means it will be called any time we modify any entry,

50
00:02:27,648 --> 00:02:28,728
like a product.

51
00:02:28,799 --> 00:02:32,709
We can leave Create, Update, and Delete all selected,

52
00:02:32,709 --> 00:02:35,659
so we'll be notified of all the changes.

53
00:02:35,733 --> 00:02:38,058
Ok, we have our webhook configured,

54
00:02:38,058 --> 00:02:39,320
so let's save this.

55
00:02:41,333 --> 00:02:43,745
Now, let's go back to our Next.js app,

56
00:02:43,745 --> 00:02:45,840
and see what we need to do there.

57
00:02:46,613 --> 00:02:50,358
First of all, let me restart the Next.js server in

58
00:02:50,358 --> 00:02:52,606
dev mode, so it will be easier

59
00:02:52,606 --> 00:02:54,703
to test our new API handler.

60
00:02:54,853 --> 00:02:57,691
But before we get to that, with on-demand

61
00:02:57,691 --> 00:02:59,837
revalidation we don't need this

62
00:02:59,837 --> 00:03:01,914
"revalidate" timeout any more.

63
00:03:02,053 --> 00:03:07,165
Because the page will be regenerated when we tell Next.js to do that,

64
00:03:07,165 --> 00:03:08,869
not based on a timeout.

65
00:03:08,943 --> 00:03:10,575
And in fact we can remove it

66
00:03:10,575 --> 00:03:12,149
from the home page as well.

67
00:03:12,323 --> 00:03:15,590
Now, we said we need an API route, so let's

68
00:03:15,590 --> 00:03:18,325
re-add the "api" folder under pages.

69
00:03:18,401 --> 00:03:22,000
And create a new file here, that we need to call

70
00:03:22,000 --> 00:03:24,175
"revalidate.js", to match the

71
00:03:24,175 --> 00:03:26,275
URL we configured in Strapi.

72
00:03:26,425 --> 00:03:28,912
So here we need a handler function,

73
00:03:28,912 --> 00:03:31,258
let's call it "handleRevalidate",

74
00:03:31,385 --> 00:03:34,294
that accepts request and response objects,

75
00:03:34,605 --> 00:03:37,669
and it should be the default export for this file.

76
00:03:40,125 --> 00:03:42,524
Now, Strapi will post a JSON

77
00:03:42,524 --> 00:03:44,666
object to this API route,

78
00:03:44,751 --> 00:03:46,659
so let's start by logging the

79
00:03:46,659 --> 00:03:48,502
data we receive from Strapi,

80
00:03:49,431 --> 00:03:51,575
that will be in the request body.

81
00:03:52,291 --> 00:03:56,683
We still need to return some response, so let's return a 204,

82
00:03:56,683 --> 00:03:58,122
which is No Content.

83
00:03:58,194 --> 00:04:00,955
Strapi only needs a successful response,

84
00:04:00,955 --> 00:04:02,819
no need to return any data.

85
00:04:02,888 --> 00:04:05,928
Ok, so let's keep an eye on the server logs,

86
00:04:05,928 --> 00:04:08,502
and go and modify some data in Strapi,

87
00:04:08,502 --> 00:04:09,857
to see what happens.

88
00:04:12,668 --> 00:04:14,997
I'll just change the first product

89
00:04:14,997 --> 00:04:16,435
to say "Aloe Vera 2",

90
00:04:16,505 --> 00:04:18,504
and when we save, Strapi will

91
00:04:18,504 --> 00:04:20,089
call our new API route,

92
00:04:20,158 --> 00:04:22,264
sending an object with lots of

93
00:04:22,264 --> 00:04:24,299
details about what's changed.

94
00:04:24,369 --> 00:04:26,330
There's an "event" property, that

95
00:04:26,330 --> 00:04:27,816
describes the event type.

96
00:04:27,876 --> 00:04:30,714
In this case it's "entry.update", because

97
00:04:30,714 --> 00:04:32,929
we modified an existing product.

98
00:04:32,998 --> 00:04:35,678
If we add a new product instead the

99
00:04:35,678 --> 00:04:37,898
event will be "entry.create".

100
00:04:37,974 --> 00:04:40,776
Another interesting field is the "model",

101
00:04:40,776 --> 00:04:42,415
that's set to "product".

102
00:04:42,484 --> 00:04:46,065
This tells us which Strapi collection we modified.

103
00:04:46,065 --> 00:04:48,753
Then there's a nested "entry" object,

104
00:04:48,753 --> 00:04:51,379
that contains all the product details,

105
00:04:51,379 --> 00:04:52,692
including its "id".

106
00:04:52,761 --> 00:04:54,519
And the "id" is in fact all

107
00:04:54,519 --> 00:04:56,147
we need for our purposes,

108
00:04:56,212 --> 00:04:58,342
so we can ignore the other properties.

109
00:04:59,252 --> 00:05:01,285
What we want to do in our code

110
00:05:01,285 --> 00:05:03,251
is look at that event object,

111
00:05:03,318 --> 00:05:05,862
that I'm going to assign to its own variable,

112
00:05:05,862 --> 00:05:07,048
just so it's clearer,

113
00:05:07,105 --> 00:05:09,532
and first of all we want to check if

114
00:05:09,532 --> 00:05:11,622
the event is about a "product",

115
00:05:11,689 --> 00:05:15,907
because we're not interested in changes to other collections,

116
00:05:15,907 --> 00:05:17,844
like cart items for example.

117
00:05:17,913 --> 00:05:20,260
If it is a Product then we can get

118
00:05:20,260 --> 00:05:22,537
its "id" from the "entry" object.

119
00:05:22,606 --> 00:05:26,150
And with this we know which pages to regenerate.

120
00:05:26,150 --> 00:05:29,825
So here we can call "res.revalidate", passing the

121
00:05:29,825 --> 00:05:33,275
path of the page that needs to be regenerated.

122
00:05:33,350 --> 00:05:35,590
If we go to our website, we display

123
00:05:35,590 --> 00:05:37,510
each product on the home page,

124
00:05:37,710 --> 00:05:41,007
(By the way, it's showing the new data now because

125
00:05:41,007 --> 00:05:43,908
we're running in dev mode, so it regenerates

126
00:05:43,908 --> 00:05:45,688
the page at every request.)

127
00:05:45,820 --> 00:05:49,457
But we also need to update the product details page,

128
00:05:49,457 --> 00:05:50,856
that's at this path.

129
00:05:50,926 --> 00:05:54,495
So in our code we want to revalidate the home page,

130
00:05:54,495 --> 00:05:56,174
that's at the root path,

131
00:05:56,244 --> 00:06:00,124
and "revalidate" is async, so we should await it.

132
00:06:00,124 --> 00:06:02,950
Then we also want to update the product page,

133
00:06:03,184 --> 00:06:06,770
but for the "id" that we received from Strapi.

134
00:06:06,770 --> 00:06:09,952
Note how we can revalidate multiple pages

135
00:06:09,952 --> 00:06:12,746
in response to a single data change.

136
00:06:12,824 --> 00:06:14,890
Now, with this code we're doing

137
00:06:14,890 --> 00:06:16,824
the revalidation in sequence:

138
00:06:16,890 --> 00:06:19,541
first the home page, and only when that's

139
00:06:19,541 --> 00:06:21,932
finished we process the product page.

140
00:06:21,997 --> 00:06:26,276
It's probably better to revalidate both pages in parallel,

141
00:06:26,276 --> 00:06:29,006
and we can do that using Promise.all.

142
00:06:29,080 --> 00:06:32,757
This takes an array with multiple promises, and will

143
00:06:32,757 --> 00:06:35,940
resolve when all the promises have completed.

144
00:06:36,010 --> 00:06:40,037
So we can pass both calls to revalidate inside the array,

145
00:06:40,037 --> 00:06:43,004
and they will effectively run in parallel.

146
00:06:43,074 --> 00:06:45,281
Ok. When it's done, we could log

147
00:06:45,281 --> 00:06:47,005
something to the console,

148
00:06:47,074 --> 00:06:49,639
so we can tell if everything worked,

149
00:06:49,639 --> 00:06:51,776
and which product was updated.

150
00:06:51,848 --> 00:06:54,421
We can remove the other log at this point.

151
00:06:55,688 --> 00:06:58,252
Ok, let's see what happens now, if we go

152
00:06:58,252 --> 00:07:00,624
and modify a product in Strapi again.

153
00:07:02,088 --> 00:07:05,232
If we look at the Next.js logs, you can see that

154
00:07:05,232 --> 00:07:08,049
it did revalidate the product with "id: 1".

155
00:07:08,114 --> 00:07:10,496
So there are no errors at least.

156
00:07:10,496 --> 00:07:15,825
But to fully test this functionality we need to run the app in production mode,

157
00:07:15,825 --> 00:07:17,175
so let's do a build.

158
00:07:17,876 --> 00:07:20,052
Now we can run "npm start".

159
00:07:20,996 --> 00:07:23,077
Ok, let's go back to the browser,

160
00:07:23,077 --> 00:07:24,906
and start from the home page.

161
00:07:25,116 --> 00:07:27,518
We currently have "Aloe Vera 3",

162
00:07:27,518 --> 00:07:29,556
Now let's change it to "4",

163
00:07:31,518 --> 00:07:33,577
and at this point we should see the

164
00:07:33,577 --> 00:07:35,577
"revalidated" message in the logs.

165
00:07:35,636 --> 00:07:38,087
Which means Next.js should have

166
00:07:38,087 --> 00:07:39,826
regenerated this page,

167
00:07:39,905 --> 00:07:43,118
and in fact the page shows "Aloe Vera 4".

168
00:07:43,118 --> 00:07:45,794
Same thing if we go back to the home page:

169
00:07:45,794 --> 00:07:48,279
the data has been updated here as well.

170
00:07:48,342 --> 00:07:50,569
Let's try testing another product.

171
00:07:50,962 --> 00:07:53,613
I'll change the "Snake Plant" this time.

172
00:07:54,862 --> 00:07:58,181
And straight away, as soon as we reload the page,

173
00:07:58,181 --> 00:08:00,552
it's showing the new product title.

174
00:08:00,620 --> 00:08:03,421
Note how with on-demand revalidation

175
00:08:03,421 --> 00:08:06,222
the new page is immediately visible,

176
00:08:06,300 --> 00:08:09,385
because it gets regenerated as soon as we

177
00:08:09,385 --> 00:08:12,470
call "res.revalidate" in the API handler.

178
00:08:12,545 --> 00:08:15,782
If you remember, when setting a "revalidate" timeout,

179
00:08:15,782 --> 00:08:17,431
like in the previous video,

180
00:08:17,492 --> 00:08:21,832
the first request after the timeout triggers the regeneration,

181
00:08:21,832 --> 00:08:23,862
but still shows the old data.

182
00:08:23,932 --> 00:08:26,102
So this is another advantage

183
00:08:26,102 --> 00:08:28,118
of on-demand revalidation.

184
00:08:28,196 --> 00:08:30,592
If you're using a CMS that supports

185
00:08:30,592 --> 00:08:32,578
calling a webhook or similar,

186
00:08:32,645 --> 00:08:35,837
I recommend using on-demand revalidation,

187
00:08:35,837 --> 00:08:38,405
rather than a revalidate timeout.

188
00:08:38,484 --> 00:08:42,404
Note that this API handler works with Strapi,

189
00:08:42,404 --> 00:08:47,317
if you use some other CMS the webhook request may be a bit different,

190
00:08:47,317 --> 00:08:49,239
and contain different data.

191
00:08:49,310 --> 00:08:52,506
So you'll need to check the documentation for that

192
00:08:52,506 --> 00:08:55,446
specific CMS to find out exactly how it works.

193
00:08:55,510 --> 00:08:58,954
Finally, I should mention that this video was added

194
00:08:58,954 --> 00:09:01,789
after the rest of the course was recorded,

195
00:09:01,857 --> 00:09:04,766
because on-demand revalidation was

196
00:09:04,766 --> 00:09:07,075
only added in Next.js 12.2.

197
00:09:07,161 --> 00:09:10,030
So in the next video you'll see the code as

198
00:09:10,030 --> 00:09:12,700
it was at the end of the previous video,

199
00:09:12,766 --> 00:09:15,506
that is using a revalidate timeout,

200
00:09:15,506 --> 00:09:17,619
not on-demand revalidation.

201
00:09:17,697 --> 00:09:21,334
If you're following along with the code, please revert

202
00:09:21,334 --> 00:09:24,096
back to the 30-second revalidate timeout,

203
00:09:24,164 --> 00:09:26,913
and disable the Strapi webhook.

204
00:09:26,913 --> 00:09:30,039
But all the concepts in the following lectures

205
00:09:30,039 --> 00:09:32,554
also apply to on-demand revalidation.

206
00:09:32,622 --> 00:09:35,852
And that includes how to set a "fallback" option

207
00:09:35,852 --> 00:09:38,408
to allow new products to be displayed,

208
00:09:38,476 --> 00:09:40,846
that is what the next video is about.

