Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
1
00:00:03,000 --> 00:00:05,423
The ReviewsPage now automatically
2
00:00:05,423 --> 00:00:07,038
lists all the reviews.
3
00:00:07,112 --> 00:00:11,185
And each individual ReviewPage is a dynamic route,
4
00:00:11,185 --> 00:00:14,384
so whenever we write a new Markdown file,
5
00:00:14,384 --> 00:00:17,393
a new page will be available automatically
6
00:00:17,393 --> 00:00:18,682
for the same path.
7
00:00:18,753 --> 00:00:22,101
But so far we only tested this dynamic
8
00:00:22,101 --> 00:00:24,215
route in the dev server.
9
00:00:24,303 --> 00:00:26,557
Let's add a log statement here,
10
00:00:26,783 --> 00:00:28,702
printing a message every time
11
00:00:28,702 --> 00:00:30,489
this component is rendered.
12
00:00:30,555 --> 00:00:32,887
And let's log the "slug" as well,
13
00:00:32,887 --> 00:00:36,576
so we can tell exactly which route was generated.
14
00:00:36,576 --> 00:00:39,336
Now, we know that the dev server
15
00:00:39,336 --> 00:00:42,962
always re-renders each page at every request.
16
00:00:42,962 --> 00:00:45,215
But what will happen in production?
17
00:00:45,215 --> 00:00:48,206
Let's stop the server, and see our how
18
00:00:48,206 --> 00:00:50,883
dynamic route works in production.
19
00:00:50,962 --> 00:00:53,591
First of all, we need to build our app,
20
00:00:53,882 --> 00:00:57,112
to create an optimized production build.
21
00:00:57,112 --> 00:00:59,804
The build output itself is quite interesting.
22
00:00:59,804 --> 00:01:02,287
If you notice, "/reviews/[slug]"
23
00:01:02,287 --> 00:01:04,691
has a lambda symbol next to it,
24
00:01:04,769 --> 00:01:07,434
not a circle like the other pages.
25
00:01:07,434 --> 00:01:09,806
At the bottom, it explains that
26
00:01:09,806 --> 00:01:11,566
the "lambda" means that
27
00:01:11,642 --> 00:01:15,603
that route "server-side renders at runtime".
28
00:01:15,603 --> 00:01:19,416
So, it's not a static page, like the other ones.
29
00:01:19,416 --> 00:01:21,709
Let's see what this means in practice,
30
00:01:21,709 --> 00:01:24,137
if we start the production server.
31
00:01:24,137 --> 00:01:25,908
Let's reload this page.
32
00:01:26,397 --> 00:01:29,179
You can see that the server rendered
33
00:01:29,179 --> 00:01:30,957
the ReviewPage 3 times:
34
00:01:31,034 --> 00:01:33,469
once for every different slug.
35
00:01:33,469 --> 00:01:36,212
Now, that's because of prefetching.
36
00:01:36,212 --> 00:01:38,489
We opened the Reviews page,
37
00:01:38,489 --> 00:01:42,028
that contains links to those three other pages,
38
00:01:42,028 --> 00:01:45,126
so the browser prefetched all the links.
39
00:01:45,126 --> 00:01:47,481
But what's more interesting thing is that
40
00:01:47,481 --> 00:01:51,177
the server rendered each page at runtime.
41
00:01:51,177 --> 00:01:53,098
This will be clearer if we look
42
00:01:53,098 --> 00:01:54,585
at an individual review.
43
00:01:54,647 --> 00:01:57,322
There's nothing new in the server logs,
44
00:01:57,322 --> 00:01:59,660
because this page had already been
45
00:01:59,660 --> 00:02:01,449
prefetched by the browser.
46
00:02:01,517 --> 00:02:03,918
But if we reload the same page,
47
00:02:03,918 --> 00:02:06,694
you can see that the server re-rendered
48
00:02:06,694 --> 00:02:08,261
the "hellblade" route.
49
00:02:08,332 --> 00:02:10,737
And every time we click reload,
50
00:02:10,737 --> 00:02:13,953
the server will re-render this page again.
51
00:02:13,953 --> 00:02:17,669
Every time the browser requests this URL path
52
00:02:17,669 --> 00:02:20,170
the server runs our component code
53
00:02:20,170 --> 00:02:24,253
and regenerates the HTML sent to the browser.
54
00:02:24,253 --> 00:02:28,284
So, this is what server-side rendering means.
55
00:02:28,284 --> 00:02:31,379
It basically works like the dev server,
56
00:02:31,379 --> 00:02:33,754
with the difference that, in production,
57
00:02:33,754 --> 00:02:36,401
it also prefetches all the links.
58
00:02:36,401 --> 00:02:39,801
But with this approach we lose the benefits
59
00:02:39,801 --> 00:02:42,174
of statically generated pages.
60
00:02:42,253 --> 00:02:45,064
Returning a static page is faster,
61
00:02:45,064 --> 00:02:48,126
because the HTML file was generated
62
00:02:48,126 --> 00:02:49,613
during the build,
63
00:02:49,700 --> 00:02:52,812
there's no need to render it at runtime.
64
00:02:52,812 --> 00:02:56,083
And also, server-side rendering requires
65
00:02:56,083 --> 00:02:58,127
running a Node.js server.
66
00:02:58,209 --> 00:03:00,957
It's not compatible with doing
67
00:03:00,957 --> 00:03:02,881
a static HTML export.
68
00:03:02,973 --> 00:03:07,066
So, is there any way to generate static pages,
69
00:03:07,066 --> 00:03:09,811
even when using a dynamic route?
70
00:03:09,811 --> 00:03:11,747
It is in fact possible.
71
00:03:11,747 --> 00:03:13,836
But we need to tell Next.js
72
00:03:13,836 --> 00:03:15,769
which routes to generate.
73
00:03:15,846 --> 00:03:19,451
Because "/reviews/[slug]" is just a pattern;
74
00:03:19,451 --> 00:03:21,921
it will match any path named
75
00:03:21,921 --> 00:03:23,862
"/reviews/" something.
76
00:03:23,950 --> 00:03:26,365
To generate some static pages
77
00:03:26,365 --> 00:03:28,446
Next.js will need to know
78
00:03:28,530 --> 00:03:31,131
exactly which "slugs" are available.
79
00:03:31,131 --> 00:03:33,633
We can provide that information
80
00:03:33,633 --> 00:03:36,054
by exporting an async function
81
00:03:36,135 --> 00:03:39,026
called "generateStaticParams".
82
00:03:39,835 --> 00:03:42,343
And here we need to return an array,
83
00:03:42,343 --> 00:03:45,149
specifying which routes are valid.
84
00:03:45,149 --> 00:03:48,433
Each element in this array must be an object,
85
00:03:48,433 --> 00:03:51,332
containing the params that will be passed
86
00:03:51,332 --> 00:03:53,312
to the ReviewPage component.
87
00:03:53,383 --> 00:03:56,518
Since this route has a "slug" parameter
88
00:03:56,518 --> 00:03:59,574
that's what we need to put inside this object.
89
00:03:59,574 --> 00:04:02,881
For example, we have a review for "hellblade".
90
00:04:02,881 --> 00:04:05,595
Then we can add another similar object,
91
00:04:05,595 --> 00:04:07,840
this time for "hollow-knight".
92
00:04:08,195 --> 00:04:11,178
Let's just return these two for the moment,
93
00:04:11,178 --> 00:04:12,961
and see what happens now,
94
00:04:13,258 --> 00:04:15,677
if we build our app for production.
95
00:04:17,418 --> 00:04:19,629
You can see that our dynamic route
96
00:04:19,629 --> 00:04:21,189
was treated differently.
97
00:04:21,254 --> 00:04:24,031
Under the "/reviews/[slug]" pattern
98
00:04:24,031 --> 00:04:26,673
there are now two specific paths:
99
00:04:26,673 --> 00:04:29,259
"hellblade", and "hollow-knight".
100
00:04:29,259 --> 00:04:32,806
Those are, of course, the two slugs we returned
101
00:04:32,806 --> 00:04:35,901
from our "generateStaticParams" function.
102
00:04:35,976 --> 00:04:38,600
Also, this route is now marked
103
00:04:38,600 --> 00:04:40,436
with a filled circle.
104
00:04:40,524 --> 00:04:43,149
At the bottom, it explains that
105
00:04:43,149 --> 00:04:45,605
that symbol stands for "SSG",
106
00:04:45,690 --> 00:04:48,670
which means "Static Site Generation".
107
00:04:48,670 --> 00:04:51,447
Now, this legend shows SSG as
108
00:04:51,447 --> 00:04:53,745
different from "Static",
109
00:04:53,841 --> 00:04:55,322
but, in practice, they're
110
00:04:55,322 --> 00:04:56,802
basically the same thing.
111
00:04:56,861 --> 00:04:59,352
SSG is also static.
112
00:04:59,352 --> 00:05:01,147
You may also notice that
113
00:05:01,147 --> 00:05:04,451
our ReviewPage was rendered during the build,
114
00:05:04,451 --> 00:05:07,244
with different values for each slug.
115
00:05:07,244 --> 00:05:09,485
This didn't happen before we
116
00:05:09,485 --> 00:05:11,647
added generateStaticParams.
117
00:05:11,727 --> 00:05:14,696
So this is how we can get Next.js
118
00:05:14,696 --> 00:05:16,945
to generate static pages,
119
00:05:17,035 --> 00:05:19,827
even when using a dynamic route.
120
00:05:19,827 --> 00:05:22,484
But we don't really want to hard-code
121
00:05:22,484 --> 00:05:24,832
all the possible slug values
122
00:05:24,832 --> 00:05:26,845
in generateStaticParams.
123
00:05:26,929 --> 00:05:28,875
We already have a "getReviews"
124
00:05:28,875 --> 00:05:30,692
function in this other file,
125
00:05:30,757 --> 00:05:33,512
that we could call to get all the reviews.
126
00:05:33,512 --> 00:05:37,204
However, this code reads each Markdown file,
127
00:05:37,204 --> 00:05:41,083
to load all the properties, like title and body.
128
00:05:41,083 --> 00:05:43,493
While in generateStaticParams
129
00:05:43,493 --> 00:05:45,404
we only need the slugs.
130
00:05:45,487 --> 00:05:49,065
So, to avoid reading many files unnecessarily,
131
00:05:49,065 --> 00:05:51,117
let's write a separate function,
132
00:05:51,885 --> 00:05:53,640
called "getSlugs".
133
00:05:54,225 --> 00:05:56,700
And here we can use the same code
134
00:05:56,700 --> 00:05:58,500
we wrote for getReviews,
135
00:05:58,575 --> 00:06:02,007
that lists all the files in the "content" folder,
136
00:06:02,007 --> 00:06:05,349
and extracts the "slugs" from the file names.
137
00:06:05,349 --> 00:06:09,300
We can simply return the slugs directly from here.
138
00:06:09,300 --> 00:06:11,371
Now, to avoid duplication, we
139
00:06:11,371 --> 00:06:13,228
can also replace this code
140
00:06:13,299 --> 00:06:16,553
with a call to our new "getSlugs" function,
141
00:06:16,553 --> 00:06:19,577
and the rest will work in the same way.
142
00:06:19,577 --> 00:06:21,915
We basically just moved some code
143
00:06:21,915 --> 00:06:23,756
into a different function.
144
00:06:23,827 --> 00:06:27,078
But this way, in "generateStaticParams",
145
00:06:27,078 --> 00:06:28,755
we can get all the "slugs"
146
00:06:28,818 --> 00:06:31,142
by awaiting the Promise returned
147
00:06:31,142 --> 00:06:32,595
by our new function.
148
00:06:32,668 --> 00:06:36,317
generateStaticParams is already async.
149
00:06:36,317 --> 00:06:38,690
Now, here we need to return an
150
00:06:38,690 --> 00:06:40,668
array like the one below,
151
00:06:40,747 --> 00:06:42,988
where each element is an object
152
00:06:42,988 --> 00:06:44,650
with a "slug" property.
153
00:06:44,723 --> 00:06:48,253
But this "slugs" variable is an array of strings.
154
00:06:48,253 --> 00:06:52,282
So we need to use "map" to transform each string
155
00:06:52,282 --> 00:06:55,472
into an object with the "slug" as a property.
156
00:06:55,472 --> 00:06:57,560
Note that we need parentheses
157
00:06:57,560 --> 00:06:59,432
around the object literal,
158
00:06:59,504 --> 00:07:02,476
otherwise JavaScript will treat the curly
159
00:07:02,476 --> 00:07:04,651
brackets as the function body.
160
00:07:04,724 --> 00:07:08,331
Anyway, we can now delete this hard-coded array,
161
00:07:08,331 --> 00:07:09,492
save this file,
162
00:07:09,492 --> 00:07:11,398
and go and build our app again,
163
00:07:11,398 --> 00:07:14,734
to see if our code works as intended.
164
00:07:15,618 --> 00:07:17,728
You can see that the dynamic route
165
00:07:17,728 --> 00:07:21,544
now resulted in three statically generated pages,
166
00:07:21,544 --> 00:07:23,638
one for each available review.
167
00:07:23,638 --> 00:07:25,330
That's what we wanted!
168
00:07:25,330 --> 00:07:27,483
Let's start the production server,
169
00:07:27,483 --> 00:07:30,400
and see how our application works now.
170
00:07:30,400 --> 00:07:32,832
If we reload the Reviews page,
171
00:07:32,832 --> 00:07:35,398
there's nothing in the server logs.
172
00:07:35,398 --> 00:07:38,178
And if we open the Hellblade review,
173
00:07:38,178 --> 00:07:41,104
even if we try reloading it a few times,
174
00:07:41,104 --> 00:07:44,604
again the server never renders any component.
175
00:07:44,604 --> 00:07:48,068
Because all the pages have been statically
176
00:07:48,068 --> 00:07:50,048
generated at build time.
177
00:07:50,130 --> 00:07:54,138
So, to recap: we can write a generateStaticParams
178
00:07:54,138 --> 00:07:54,792
function
179
00:07:54,874 --> 00:07:57,406
returning all the possible paths,
180
00:07:57,406 --> 00:08:00,118
and Next.js will generate static
181
00:08:00,118 --> 00:08:02,745
pages even for a dynamic route.
13237
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.