1
00:00:03,000 --> 00:00:06,085
By implementing the PaginationBar component,

2
00:00:06,085 --> 00:00:09,833
our pagination functionality is now fully working.

3
00:00:09,833 --> 00:00:12,251
Our users can see all the reviews

4
00:00:12,251 --> 00:00:13,789
available in the CMS,

5
00:00:13,862 --> 00:00:17,506
and the next link is disabled on the last page.

6
00:00:17,506 --> 00:00:19,769
Now, what we haven't done yet

7
00:00:19,769 --> 00:00:22,401
is see how this new functionality

8
00:00:22,401 --> 00:00:23,995
works in production.

9
00:00:24,075 --> 00:00:27,542
In the ReviewsPage we're using "searchParams",

10
00:00:27,542 --> 00:00:29,747
and this has some implications

11
00:00:29,747 --> 00:00:32,399
on how that page will be rendered.

12
00:00:32,399 --> 00:00:35,204
The Next.js documentation says that

13
00:00:35,204 --> 00:00:38,577
"searchParams is a Dynamic API whose values

14
00:00:38,577 --> 00:00:41,008
cannot be known ahead of time."

15
00:00:41,087 --> 00:00:44,458
"Using it will opt the page into dynamic

16
00:00:44,458 --> 00:00:46,734
rendering at request time."

17
00:00:46,818 --> 00:00:49,180
So, by using "searchParams"

18
00:00:49,180 --> 00:00:51,833
our page will be treated as dynamic.

19
00:00:51,833 --> 00:00:54,667
Because it's impossible to know in advance

20
00:00:54,667 --> 00:00:56,545
which values will be passed

21
00:00:56,545 --> 00:00:58,423
as query string parameters,

22
00:00:58,493 --> 00:01:01,719
and that's why Next.js cannot generate

23
00:01:01,719 --> 00:01:04,012
static pages at build time.

24
00:01:04,096 --> 00:01:06,185
Let's go and do a production build,

25
00:01:06,185 --> 00:01:07,774
to see this in action.

26
00:01:07,774 --> 00:01:10,326
I'll delete the ".next" folder and

27
00:01:10,326 --> 00:01:12,652
do an "npm run build" as usual.

28
00:01:13,174 --> 00:01:16,127
We can already see that the "/reviews"

29
00:01:16,127 --> 00:01:17,447
route is dynamic:

30
00:01:17,525 --> 00:01:20,205
it has a lambda symbol next to it.

31
00:01:20,205 --> 00:01:22,399
Just like the documentation said,

32
00:01:22,399 --> 00:01:26,814
Next.js detected that our code uses "searchParams"

33
00:01:26,814 --> 00:01:30,815
and therefore it's treating that route as dynamic.

34
00:01:30,815 --> 00:01:33,425
Now, let's start the production server.

35
00:01:33,425 --> 00:01:36,143
If we go and reload the Reviews page,

36
00:01:36,397 --> 00:01:38,613
we can see in the server logs

37
00:01:38,613 --> 00:01:40,676
that it renders at runtime.

38
00:01:40,753 --> 00:01:43,706
Let me clear the logs and reload it again.

39
00:01:43,905 --> 00:01:45,840
It rendered page 1, that's the

40
00:01:45,840 --> 00:01:47,517
one we see in the browser,

41
00:01:47,581 --> 00:01:51,339
and then it also rendered page 1 again and 2.

42
00:01:51,339 --> 00:01:54,110
That's because of link prefetching.

43
00:01:54,110 --> 00:01:56,048
The link in the NavBar doesn't

44
00:01:56,048 --> 00:01:57,663
pass the "page" parameter

45
00:01:57,727 --> 00:01:59,845
so it's effectively for page 1,

46
00:01:59,845 --> 00:02:03,538
and then the next link in the PaginationBar

47
00:02:03,538 --> 00:02:04,998
points to page 2.

48
00:02:05,084 --> 00:02:08,032
We could actually disable the NavBar link

49
00:02:08,032 --> 00:02:09,997
if we're already on that page.

50
00:02:09,997 --> 00:02:11,718
Anyway, if we reload,

51
00:02:11,718 --> 00:02:14,958
it re-renders all the same pages again.

52
00:02:14,958 --> 00:02:16,913
Because dynamic rendering

53
00:02:16,913 --> 00:02:18,869
happens at every request.

54
00:02:18,947 --> 00:02:21,022
Now, if we go to the next page,

55
00:02:21,022 --> 00:02:23,988
it rendered pages 3 and 1,

56
00:02:23,988 --> 00:02:26,660
that are the next and previous links.

57
00:02:26,660 --> 00:02:29,590
It didn't actually render page 2 because

58
00:02:29,590 --> 00:02:31,686
it had already been prefetched

59
00:02:31,686 --> 00:02:33,783
when we loaded the first page.

60
00:02:33,852 --> 00:02:35,333
And if we keep going,

61
00:02:35,445 --> 00:02:37,801
it will only render the new links.

62
00:02:37,801 --> 00:02:40,209
But again, if we reload the page,

63
00:02:40,209 --> 00:02:43,392
it re-renders that specific page number,

64
00:02:43,392 --> 00:02:46,416
along with any links found on that page.

65
00:02:46,416 --> 00:02:48,772
This is the same behaviour we've seen

66
00:02:48,772 --> 00:02:51,123
when we configured dynamic rendering

67
00:02:51,123 --> 00:02:52,689
in the previous section.

68
00:02:52,755 --> 00:02:56,459
But it's now enabled because of "searchParams".

69
00:02:56,459 --> 00:02:58,787
Now, is there any way we could

70
00:02:58,787 --> 00:03:00,417
use static rendering,

71
00:03:00,494 --> 00:03:03,051
even for a route with pagination?

72
00:03:03,051 --> 00:03:05,392
We could, but we'd need to use

73
00:03:05,392 --> 00:03:07,344
a path parameter instead,

74
00:03:07,422 --> 00:03:10,276
like we do for the "slug" in the ReviewPage.

75
00:03:10,276 --> 00:03:12,713
Rather than passing the page number

76
00:03:12,713 --> 00:03:15,080
after the question mark in the URL

77
00:03:15,149 --> 00:03:18,058
we would need it to be a path segment.

78
00:03:18,058 --> 00:03:20,189
We could have URLs like

79
00:03:20,189 --> 00:03:24,312
"/reviews/page/1", "/reviews/page/2", and so on.

80
00:03:24,312 --> 00:03:26,814
With this approach, we could then write

81
00:03:26,814 --> 00:03:28,930
a "generateStaticParams" function

82
00:03:28,994 --> 00:03:32,097
and return all the possible page numbers,

83
00:03:32,097 --> 00:03:34,348
so Next.js can generate all

84
00:03:34,348 --> 00:03:36,265
these pages statically.

85
00:03:36,349 --> 00:03:38,329
This is a possible option,

86
00:03:38,329 --> 00:03:40,998
and we could implement it in our application,

87
00:03:40,998 --> 00:03:41,769
if we wanted.

88
00:03:41,828 --> 00:03:45,413
The choice between path and "searchParams"

89
00:03:45,413 --> 00:03:48,493
depends on how you look at the parameter values.

90
00:03:48,493 --> 00:03:50,424
If you think of them as a

91
00:03:50,424 --> 00:03:52,354
set of predefined options

92
00:03:52,432 --> 00:03:54,540
then it makes sense to accept

93
00:03:54,540 --> 00:03:56,213
them as path parameters

94
00:03:56,286 --> 00:03:58,339
and generate them statically.

95
00:03:58,339 --> 00:04:00,693
While if you see the parameters

96
00:04:00,693 --> 00:04:02,136
as arbitrary values

97
00:04:02,212 --> 00:04:04,763
used to generate a custom page

98
00:04:04,763 --> 00:04:06,633
for that specific user

99
00:04:06,719 --> 00:04:10,566
then the choice has to be dynamic searchParams.

100
00:04:10,566 --> 00:04:12,587
In our example, at the moment

101
00:04:12,587 --> 00:04:14,607
the page number could be seen

102
00:04:14,677 --> 00:04:16,688
more like a choice between

103
00:04:16,688 --> 00:04:18,700
predefined static options.

104
00:04:18,777 --> 00:04:20,951
But imagine that we also plan to

105
00:04:20,951 --> 00:04:23,125
add filters to the Reviews page,

106
00:04:23,193 --> 00:04:25,810
allowing users to select only games

107
00:04:25,810 --> 00:04:28,277
of a certain "genre" for example,

108
00:04:28,352 --> 00:04:30,781
and possibly combine that with the

109
00:04:30,781 --> 00:04:33,138
"platform" supported by the game,

110
00:04:33,210 --> 00:04:36,309
and maybe even search by arbitrary keywords.

111
00:04:36,309 --> 00:04:38,515
And the search results always

112
00:04:38,515 --> 00:04:40,112
need to be paginated.

113
00:04:40,188 --> 00:04:42,047
In this case, you can see how

114
00:04:42,047 --> 00:04:43,712
it would be very difficult

115
00:04:43,776 --> 00:04:46,664
to statically generate all the possible

116
00:04:46,664 --> 00:04:48,960
combinations of search options.

117
00:04:49,034 --> 00:04:52,058
This kind of URL needs to be dynamic,

118
00:04:52,058 --> 00:04:55,207
because the page it generates is effectively

119
00:04:55,207 --> 00:04:57,569
custom-tailored for each request.

120
00:04:57,640 --> 00:05:01,495
So we'll keep using "searchParams" for pagination,

121
00:05:01,495 --> 00:05:04,094
in case we want to add custom search

122
00:05:04,094 --> 00:05:06,260
options to filter the reviews.

123
00:05:06,333 --> 00:05:08,608
It's important to point out that

124
00:05:08,608 --> 00:05:11,812
dynamic rendering doesn't necessarily mean

125
00:05:11,812 --> 00:05:14,482
fetching new data at every request.

126
00:05:14,558 --> 00:05:17,205
Note that we didn't configure this

127
00:05:17,205 --> 00:05:19,385
page to use "force-dynamic",

128
00:05:19,463 --> 00:05:22,107
like we did in the previous section when

129
00:05:22,107 --> 00:05:24,553
we first looked at dynamic rendering.

130
00:05:24,620 --> 00:05:26,991
If you remember, the "dynamic"

131
00:05:26,991 --> 00:05:29,204
behavior defaults to "auto",

132
00:05:29,283 --> 00:05:32,948
and in this case it's Next.js that automatically

133
00:05:32,948 --> 00:05:35,468
decides to use dynamic rendering,

134
00:05:35,544 --> 00:05:38,755
because our code reads the "searchParams".

135
00:05:38,755 --> 00:05:42,557
But Next.js will still cache fetch requests,

136
00:05:42,557 --> 00:05:44,988
because we didn't set any options

137
00:05:44,988 --> 00:05:46,978
to disable the fetch cache.

138
00:05:47,052 --> 00:05:50,715
We only set a tag used for revalidation,

139
00:05:50,715 --> 00:05:52,959
and in fact the data in the cache

140
00:05:52,959 --> 00:05:54,659
will still be invalidated

141
00:05:54,727 --> 00:05:57,045
when Strapi calls our webhook.

142
00:05:57,045 --> 00:06:00,732
But otherwise all fetch requests will be cached,

143
00:06:00,732 --> 00:06:03,085
because that's the default behavior.

144
00:06:03,085 --> 00:06:05,056
This is different from when

145
00:06:05,056 --> 00:06:06,735
we set "force-dynamic",

146
00:06:06,808 --> 00:06:09,196
because "force-dynamic" also

147
00:06:09,196 --> 00:06:11,328
disables the fetch cache.

148
00:06:11,413 --> 00:06:13,593
Let's see what this means in practice.

149
00:06:13,697 --> 00:06:15,724
If I show you the terminal where

150
00:06:15,724 --> 00:06:17,118
I have Strapi running,

151
00:06:17,181 --> 00:06:19,301
as you can see Strapi logs all

152
00:06:19,301 --> 00:06:21,068
the requests it receives.

153
00:06:21,139 --> 00:06:23,694
Let me add a separator here, so it's

154
00:06:23,694 --> 00:06:25,610
easier to see new requests.

155
00:06:25,681 --> 00:06:28,352
If I go and reload the Reviews page,

156
00:06:28,352 --> 00:06:30,725
you can see in the Next.js logs

157
00:06:30,725 --> 00:06:32,791
that the page was rendered,

158
00:06:32,868 --> 00:06:35,008
however we don't see any new

159
00:06:35,008 --> 00:06:37,148
requests in the Strapi logs.

160
00:06:37,224 --> 00:06:41,063
That's because Next.js is using the fetch cache.

161
00:06:41,063 --> 00:06:43,535
It already had all the data displayed

162
00:06:43,535 --> 00:06:45,271
on this page in the cache;

163
00:06:45,338 --> 00:06:48,892
that's why it didn't send any requests to Strapi.

164
00:06:48,892 --> 00:06:51,212
Every time we load this page,

165
00:06:51,212 --> 00:06:52,972
Next.js re-renders it,

166
00:06:53,052 --> 00:06:54,842
but all the data is already

167
00:06:54,842 --> 00:06:56,367
available in the cache,

168
00:06:56,433 --> 00:06:59,298
it doesn't need to be loaded from the CMS.

169
00:06:59,298 --> 00:07:01,548
Rendering the page dynamically

170
00:07:01,548 --> 00:07:05,289
will still be slower than returning a static file,

171
00:07:05,289 --> 00:07:08,158
but it's also faster than refetching

172
00:07:08,158 --> 00:07:10,787
the data from the CMS every time.

173
00:07:10,867 --> 00:07:13,520
Now, if we restart from page 1,

174
00:07:13,520 --> 00:07:14,639
we should see that

175
00:07:14,639 --> 00:07:17,418
we can load the first 3 pages without

176
00:07:17,418 --> 00:07:19,672
making any requests to Strapi,

177
00:07:19,747 --> 00:07:23,145
because we already opened these pages before,

178
00:07:23,145 --> 00:07:26,388
and so all the data was in the fetch cache.

179
00:07:26,388 --> 00:07:28,417
But if we go to Page 4,

180
00:07:28,417 --> 00:07:30,636
we didn't open this one earlier,

181
00:07:30,636 --> 00:07:33,381
and that's why this time we do see some

182
00:07:33,381 --> 00:07:35,633
new requests in the Strapi logs.

183
00:07:35,704 --> 00:07:37,696
Most of them are for images,

184
00:07:37,696 --> 00:07:40,457
which is not what we're interested in right now.

185
00:07:40,457 --> 00:07:42,234
But you can see that there's

186
00:07:42,234 --> 00:07:43,694
also an "/api" request,

187
00:07:43,758 --> 00:07:46,504
fetching the reviews for page 5.

188
00:07:46,504 --> 00:07:48,402
That may seem a bit strange,

189
00:07:48,402 --> 00:07:51,602
because we opened page 4 in the browser,

190
00:07:51,602 --> 00:07:54,841
but it's always because of link prefetching.

191
00:07:54,841 --> 00:07:58,735
Page 5 is what the next link points to.

192
00:07:58,735 --> 00:08:01,412
It didn't fetch page 4 because it had

193
00:08:01,412 --> 00:08:03,654
already been requested earlier;

194
00:08:03,727 --> 00:08:08,013
it was prefetched from the next link on page 3.

195
00:08:08,013 --> 00:08:10,234
In fact, if we go to page 5,

196
00:08:10,234 --> 00:08:13,285
it doesn't need to make any new "/api" requests

197
00:08:13,285 --> 00:08:15,876
because it already fetched the data

198
00:08:15,876 --> 00:08:18,245
for page 5 in the previous step.

199
00:08:18,319 --> 00:08:21,343
It only loaded the image we see on this page.

200
00:08:21,343 --> 00:08:24,428
Once we make a request for a certain URL

201
00:08:24,428 --> 00:08:28,317
Next.js will cache and reuse the response,

202
00:08:28,317 --> 00:08:32,506
so from now on it won't make any new CMS request

203
00:08:32,506 --> 00:08:35,898
no matter how many times we reload page 4.

204
00:08:35,898 --> 00:08:39,092
If you modify something in the CMS however,

205
00:08:39,092 --> 00:08:41,929
that will trigger on-demand revalidation,

206
00:08:41,929 --> 00:08:44,118
and at that point you should see that

207
00:08:44,118 --> 00:08:46,271
Next.js will make new fetch

208
00:08:46,271 --> 00:08:48,344
requests for all the data.

209
00:08:48,423 --> 00:08:50,721
Anyway, the main point is that

210
00:08:50,721 --> 00:08:52,777
even though our ReviewsPage

211
00:08:52,777 --> 00:08:54,529
is rendered dynamically

212
00:08:54,605 --> 00:08:56,940
the data fetched from the CMS

213
00:08:56,940 --> 00:08:58,712
is still being cached.

214
00:08:58,793 --> 00:09:01,082
So using "searchParams" is

215
00:09:01,082 --> 00:09:03,372
not as bad for performance

216
00:09:03,460 --> 00:09:06,186
as it would be without the fetch cache.

