1
00:00:03,000 --> 00:00:04,963
We wrote a route handler,

2
00:00:04,963 --> 00:00:08,197
so we can receive notifications from Strapi,

3
00:00:08,197 --> 00:00:11,112
whenever the data in the CMS is modified.

4
00:00:11,112 --> 00:00:13,592
And we tested it using the Trigger

5
00:00:13,592 --> 00:00:15,051
button on this page.

6
00:00:15,124 --> 00:00:16,912
But let's see how it works

7
00:00:16,912 --> 00:00:18,630
if we make a real change.

8
00:00:18,699 --> 00:00:20,764
For example, we could delete

9
00:00:20,764 --> 00:00:22,681
this "subnautica-2" entry,

10
00:00:22,755 --> 00:00:25,710
that we created in one of our previous tests.

11
00:00:25,710 --> 00:00:29,189
Let's go and see what was sent to our webhook.

12
00:00:29,189 --> 00:00:32,521
The notification includes all the entry fields.

13
00:00:32,521 --> 00:00:35,028
But it also has an "event" property,

14
00:00:35,028 --> 00:00:38,643
that tells us what type of change occurred.

15
00:00:38,643 --> 00:00:41,289
In this case it's "entry.delete".

16
00:00:41,289 --> 00:00:44,470
Another useful property is "model",

17
00:00:44,470 --> 00:00:48,344
that specifies which collection type was modified,

18
00:00:48,344 --> 00:00:52,289
in case we have different object types in the CMS.

19
00:00:52,289 --> 00:00:54,100
Now, let me clear the logs,

20
00:00:54,100 --> 00:00:56,912
and try a different type of change.

21
00:00:56,912 --> 00:01:00,248
Let's see what happens when we create a new entry.

22
00:01:00,248 --> 00:01:01,925
I'll duplicate this one,

23
00:01:01,925 --> 00:01:04,251
and change it to "celeste-2",

24
00:01:04,485 --> 00:01:06,849
both in the slug and in the title.

25
00:01:06,849 --> 00:01:09,324
Let's see what kind of notification

26
00:01:09,324 --> 00:01:10,738
we get in this case.

27
00:01:10,809 --> 00:01:13,689
The "event" is now "entry.create".

28
00:01:13,689 --> 00:01:15,988
And again we get all the fields.

29
00:01:15,988 --> 00:01:19,003
But note that "publishedAt" is "null",

30
00:01:19,003 --> 00:01:22,122
because we haven't actually published the entry.

31
00:01:22,122 --> 00:01:24,338
It's still a "draft version".

32
00:01:24,338 --> 00:01:26,258
Let's go and publish it now.

33
00:01:26,464 --> 00:01:29,561
And see what kind of event we get this time.

34
00:01:29,561 --> 00:01:32,357
There is one saying "entry.update",

35
00:01:32,357 --> 00:01:35,416
because publishing a review also updates

36
00:01:35,416 --> 00:01:38,245
its record in the database I suppose.

37
00:01:38,322 --> 00:01:41,246
But then we also receive another notification,

38
00:01:41,246 --> 00:01:44,165
with "entry.publish" as the event.

39
00:01:44,165 --> 00:01:46,616
So we get two notifications:

40
00:01:46,616 --> 00:01:48,629
"update" and "publish".

41
00:01:48,717 --> 00:01:51,777
Now, we could write some checks in our code

42
00:01:51,777 --> 00:01:54,344
to make sure we only regenerate our pages

43
00:01:54,344 --> 00:01:56,723
when the review is actually published,

44
00:01:56,786 --> 00:01:58,912
not when it's still in draft.

45
00:01:58,912 --> 00:02:01,761
And also to only revalidate once

46
00:02:01,761 --> 00:02:03,943
even if we receive two different

47
00:02:03,943 --> 00:02:06,125
notifications like in this case.

48
00:02:06,193 --> 00:02:08,056
But, to keep things simple,

49
00:02:08,056 --> 00:02:09,982
I'm only going to check if the

50
00:02:09,982 --> 00:02:11,715
change is about a "review".

51
00:02:11,779 --> 00:02:13,873
Even if we revalidate when it's

52
00:02:13,873 --> 00:02:15,360
not strictly necessary

53
00:02:15,427 --> 00:02:17,397
that's not really a big deal.

54
00:02:17,397 --> 00:02:21,242
So in our handler let's check the "payload.model"

55
00:02:21,242 --> 00:02:23,918
and only do something if it's a "review".

56
00:02:24,560 --> 00:02:27,757
Now, here we want to trigger the revalidation.

57
00:02:27,757 --> 00:02:29,445
Let's take another look at

58
00:02:29,445 --> 00:02:31,133
the Next.js documentation.

59
00:02:31,198 --> 00:02:33,517
In our route handler we can call

60
00:02:33,517 --> 00:02:35,620
the "revalidateTag" function,

61
00:02:35,692 --> 00:02:38,176
passing a "tag" that identifies

62
00:02:38,176 --> 00:02:40,260
a certain "fetch" request.

63
00:02:40,340 --> 00:02:42,942
This will effectively invalidate the

64
00:02:42,942 --> 00:02:45,327
data cached by that "fetch" call.

65
00:02:45,399 --> 00:02:48,115
So, in our code we need to start from

66
00:02:48,115 --> 00:02:50,375
where we make the "fetch" request.

67
00:02:50,375 --> 00:02:53,079
Instead of setting a "revalidate" interval

68
00:02:53,079 --> 00:02:54,725
we want to pass some "tags",

69
00:02:55,139 --> 00:02:56,669
that's an array of strings.

70
00:02:56,669 --> 00:02:59,093
Now, a "tag" is just an arbitrary

71
00:02:59,093 --> 00:03:00,488
value we can choose

72
00:03:00,562 --> 00:03:03,727
to identify one or more fetch requests.

73
00:03:03,727 --> 00:03:06,250
So I'll use "reviews" for this one.

74
00:03:06,250 --> 00:03:09,762
But since we'll need to use exactly the same value

75
00:03:09,762 --> 00:03:11,829
when triggering the revalidation,

76
00:03:11,829 --> 00:03:14,364
it's better if we define a constant,

77
00:03:14,364 --> 00:03:15,349
and export it.

78
00:03:15,420 --> 00:03:17,910
Let's call it "CACHE_TAG_REVIEWS".

79
00:03:18,945 --> 00:03:21,044
This way we'll be able to import

80
00:03:21,044 --> 00:03:22,749
it into the route handler.

81
00:03:22,814 --> 00:03:25,122
But first let's use it in this file,

82
00:03:25,821 --> 00:03:28,102
passing it in the "tags" array.

83
00:03:28,340 --> 00:03:30,301
Note that, by doing this here,

84
00:03:30,301 --> 00:03:33,948
the tag will apply to all CMS requests.

85
00:03:33,948 --> 00:03:36,535
Because this "fetchReviews" function

86
00:03:36,535 --> 00:03:37,901
is the shared code,

87
00:03:37,973 --> 00:03:41,412
called by both "getReview" and "getReviews" ,

88
00:03:41,412 --> 00:03:43,398
with different parameters.

89
00:03:43,475 --> 00:03:45,704
So this tag will be applied to

90
00:03:45,704 --> 00:03:47,785
both the individual reviews,

91
00:03:47,860 --> 00:03:50,281
and the lists displayed in the

92
00:03:50,281 --> 00:03:52,137
Home and Reviews pages.

93
00:03:52,218 --> 00:03:54,849
This is what we want in this application,

94
00:03:54,849 --> 00:03:58,014
because when we modify an entry in the CMS

95
00:03:58,014 --> 00:04:01,354
we want to update both the page for that review,

96
00:04:01,354 --> 00:04:05,422
and all the pages were that entry is listed.

97
00:04:05,422 --> 00:04:07,892
Let's go to our route handler now.

98
00:04:07,892 --> 00:04:10,743
Here we want to call "revalidateTag",

99
00:04:10,774 --> 00:04:12,712
that's a function provided by

100
00:04:12,712 --> 00:04:14,316
the "next/cache" module.

101
00:04:14,383 --> 00:04:16,575
And pass it our custom tag

102
00:04:16,575 --> 00:04:20,103
that we exported from our "lib/reviews" module.

103
00:04:20,103 --> 00:04:23,982
Again, this will invalidate any data in the cache

104
00:04:23,982 --> 00:04:26,167
stored from "fetch" requests

105
00:04:26,167 --> 00:04:27,963
labelled with this tag.

106
00:04:28,041 --> 00:04:30,318
Let's log something in this case.

107
00:04:30,448 --> 00:04:32,346
We could print "revalidated"

108
00:04:32,346 --> 00:04:34,685
followed by the tag value.

109
00:04:34,685 --> 00:04:36,652
Ok, let's save our code,

110
00:04:36,652 --> 00:04:38,639
and test this functionality.

111
00:04:38,639 --> 00:04:40,775
We need to do a production build

112
00:04:40,835 --> 00:04:43,430
because we cannot test revalidation

113
00:04:43,430 --> 00:04:44,764
in the dev server.

114
00:04:46,335 --> 00:04:49,699
Note that there's a new route for the webhook,

115
00:04:49,699 --> 00:04:51,661
and it's shown as dynamic,

116
00:04:51,661 --> 00:04:53,918
because the route handler will

117
00:04:53,918 --> 00:04:56,176
be executed for every request.

118
00:04:56,251 --> 00:04:58,371
But let's start the server now

119
00:04:58,673 --> 00:05:00,733
and go and test our application.

120
00:05:01,331 --> 00:05:03,328
Let me put the browser on the right,

121
00:05:04,135 --> 00:05:06,315
and start from the Home page.

122
00:05:06,487 --> 00:05:09,382
All pages have been statically generated,

123
00:05:09,382 --> 00:05:12,205
so when we load them the first time

124
00:05:12,205 --> 00:05:15,225
the server doesn't need to rerender anything.

125
00:05:15,225 --> 00:05:17,412
But let's see what happens if we go

126
00:05:17,412 --> 00:05:19,411
and change something in the CMS.

127
00:05:19,947 --> 00:05:22,688
I'll just modify this existing review,

128
00:05:22,688 --> 00:05:25,222
and add "update 1" to the title.

129
00:05:25,543 --> 00:05:27,845
If we go back to our Next.js app,

130
00:05:28,004 --> 00:05:29,716
you can see in the logs that

131
00:05:29,716 --> 00:05:31,554
our webhook was called,

132
00:05:31,554 --> 00:05:34,312
and revalidated all fetch requests

133
00:05:34,312 --> 00:05:36,097
tagged with "reviews".

134
00:05:36,178 --> 00:05:38,478
So, if we reload the Home page,

135
00:05:38,918 --> 00:05:40,837
we see a bunch of "rendering"

136
00:05:40,837 --> 00:05:42,226
messages in the logs.

137
00:05:42,292 --> 00:05:44,538
Because the server detected that

138
00:05:44,538 --> 00:05:47,685
the data in the cache was no longer valid,

139
00:05:47,685 --> 00:05:51,412
and therefore these pages had to be regenerated.

140
00:05:51,412 --> 00:05:54,696
But note that the re-rendering only happened

141
00:05:54,696 --> 00:05:57,379
when we requested a page in the browser.

142
00:05:57,379 --> 00:05:59,661
Simply calling "revalidateTag"

143
00:05:59,661 --> 00:06:01,183
in our route handler

144
00:06:01,259 --> 00:06:03,356
doesn't cause the pages to be

145
00:06:03,356 --> 00:06:05,092
regenerated immediately.

146
00:06:05,165 --> 00:06:08,888
It only marks the data in the cache as invalid.

147
00:06:08,888 --> 00:06:10,903
In fact you can also see that

148
00:06:10,903 --> 00:06:14,579
the page in the browser still shows the old title.

149
00:06:14,579 --> 00:06:16,769
That's because, just like with

150
00:06:16,769 --> 00:06:18,521
time-based revalidation,

151
00:06:18,594 --> 00:06:22,293
the first request still receives the old page.

152
00:06:22,293 --> 00:06:25,699
The new page will be returned if we reload again.

153
00:06:25,699 --> 00:06:29,190
You can see that it shows the updated title now.

154
00:06:29,190 --> 00:06:31,245
At this point all other pages

155
00:06:31,245 --> 00:06:33,300
should be up to date as well.

156
00:06:33,371 --> 00:06:35,511
Because all fetch requests are

157
00:06:35,511 --> 00:06:37,438
labelled with the same tag,

158
00:06:37,509 --> 00:06:40,048
so by calling "revalidateTag"

159
00:06:40,048 --> 00:06:43,623
we invalidate all the cached CMS data.

160
00:06:43,623 --> 00:06:47,384
And therefore Next.js regenerates all the pages

161
00:06:47,384 --> 00:06:49,290
that were using that data.

162
00:06:49,290 --> 00:06:53,019
And this is how on-demand revalidation works.

163
00:06:53,019 --> 00:06:55,645
We expose a webhook that receives

164
00:06:55,645 --> 00:06:57,793
notifications from the CMS,

165
00:06:57,873 --> 00:07:00,527
and then we call revalidateTag,

166
00:07:00,527 --> 00:07:03,078
passing the same tag we specify when

167
00:07:03,078 --> 00:07:05,062
making the "fetch" requests.

168
00:07:05,133 --> 00:07:07,227
This way we can make sure that

169
00:07:07,227 --> 00:07:10,435
any data in the cache is invalidated

170
00:07:10,435 --> 00:07:13,360
as soon as we modify it in the CMS.

