1
00:00:03,000 --> 00:00:06,040
We're currently displaying product images

2
00:00:06,040 --> 00:00:08,710
using a standard HTML "img" element.

3
00:00:09,285 --> 00:00:12,462
But as I mentioned at the end of the last video

4
00:00:12,462 --> 00:00:14,760
this way the images are downloaded

5
00:00:14,760 --> 00:00:16,315
at their original size,

6
00:00:16,315 --> 00:00:17,938
that is larger than what

7
00:00:17,938 --> 00:00:19,966
we're displaying on this page.

8
00:00:19,966 --> 00:00:22,332
Also, all the images will be loaded

9
00:00:22,332 --> 00:00:24,225
as soon as we load the page,

10
00:00:24,225 --> 00:00:26,997
even though some of them are not visible,

11
00:00:26,997 --> 00:00:29,228
because they're "below the fold",

12
00:00:29,228 --> 00:00:32,270
meaning we'd need to scroll down to see them.

13
00:00:33,379 --> 00:00:36,801
Thankfully Next.js comes with some nifty features

14
00:00:36,801 --> 00:00:38,757
around "Image Optimization".

15
00:00:39,327 --> 00:00:42,120
It provides a component called Next Image,

16
00:00:42,120 --> 00:00:44,314
and some functionality built into

17
00:00:44,314 --> 00:00:45,578
the Next.js server,

18
00:00:46,211 --> 00:00:49,197
so that it can automatically resize images

19
00:00:49,197 --> 00:00:52,325
to match the dimensions we use in our pages.

20
00:00:52,897 --> 00:00:55,241
It can convert those images

21
00:00:55,241 --> 00:00:57,673
to modern formats like WebP,

22
00:00:57,673 --> 00:01:00,712
that take up less space compared to

23
00:01:00,712 --> 00:01:02,796
older formats like JPEG.

24
00:01:03,557 --> 00:01:06,666
Finally it allows us to lazy load our images,

25
00:01:06,666 --> 00:01:09,362
which means loading only those that are

26
00:01:09,362 --> 00:01:11,573
currently visible on the screen.

27
00:01:12,212 --> 00:01:15,467
Now, the way the Next.js server does all this

28
00:01:15,467 --> 00:01:16,552
is "on-demand".

29
00:01:17,125 --> 00:01:19,185
Which means that for example

30
00:01:19,185 --> 00:01:21,466
if an image needs to be resized

31
00:01:21,466 --> 00:01:23,748
that will happen the first time

32
00:01:23,748 --> 00:01:26,544
we request that image from the server.

33
00:01:26,544 --> 00:01:29,267
So this doesn't happen at build time.

34
00:01:29,267 --> 00:01:31,916
Next.js will not statically generate

35
00:01:31,916 --> 00:01:35,007
all possible images when we build the app.

36
00:01:35,007 --> 00:01:38,760
But as we'll see it will cache the generated images

37
00:01:38,760 --> 00:01:41,483
after they've been resized on-demand.

38
00:01:42,572 --> 00:01:44,814
Anyway, enough of introductions

39
00:01:44,814 --> 00:01:47,346
and let's see how it works in code.

40
00:01:47,918 --> 00:01:50,091
The central piece of the puzzle

41
00:01:50,091 --> 00:01:51,773
is the "Image" component

42
00:01:51,773 --> 00:01:54,296
exported by the "next/image" module.

43
00:01:54,936 --> 00:01:58,462
We can use this component simply as a replacement

44
00:01:58,462 --> 00:02:01,052
for the standard HTML "img" element.

45
00:02:01,623 --> 00:02:04,077
But typically we also need to specify

46
00:02:04,077 --> 00:02:05,602
the dimensions we want.

47
00:02:06,524 --> 00:02:08,876
Let's set the "width" to 320

48
00:02:08,876 --> 00:02:12,068
and the "height" to "240", as numbers.

49
00:02:12,068 --> 00:02:15,680
This way we can let the Next.js server know

50
00:02:15,680 --> 00:02:18,536
how it should resize these images.

51
00:02:19,288 --> 00:02:20,157
If we save now,

52
00:02:22,155 --> 00:02:23,944
we actually get an error.

53
00:02:23,944 --> 00:02:25,805
It says "Invalid src prop"

54
00:02:25,805 --> 00:02:28,596
"hostname localhost is not configured".

55
00:02:29,240 --> 00:02:32,109
And it includes a link where we can find more info,

56
00:02:32,109 --> 00:02:33,965
so let's read this documentation.

57
00:02:34,522 --> 00:02:36,482
Here it basically says that

58
00:02:36,482 --> 00:02:39,168
we need to specify from which servers

59
00:02:39,168 --> 00:02:41,709
we want to be able to fetch images,

60
00:02:41,709 --> 00:02:44,251
adding them to a configuration file

61
00:02:44,251 --> 00:02:45,993
called "next.config.js".

62
00:02:45,993 --> 00:02:49,333
So this is essentially a security restriction.

63
00:02:49,333 --> 00:02:51,801
You don't want your Next.js server

64
00:02:51,801 --> 00:02:55,141
to fetch images from anywhere on the internet,

65
00:02:55,141 --> 00:02:57,247
because that could be abused.

66
00:02:57,247 --> 00:03:00,006
You only want to allow images from one

67
00:03:00,006 --> 00:03:02,619
or maybe a few predefined locations.

68
00:03:03,846 --> 00:03:07,608
Now, we should already have that configuration file

69
00:03:07,608 --> 00:03:09,379
called "next.config.js".

70
00:03:09,379 --> 00:03:11,961
It was generated by Create Next App

71
00:03:11,961 --> 00:03:14,469
when we first set up this project.

72
00:03:15,191 --> 00:03:18,166
So let's copy the bit about "images" from here,

73
00:03:18,666 --> 00:03:21,641
and add it to our "next.config.js".

74
00:03:22,141 --> 00:03:24,047
But we need to change the domain.

75
00:03:24,547 --> 00:03:26,448
In our case we're fetching images

76
00:03:26,448 --> 00:03:29,502
from our Strapi server that's running on "localhost".

77
00:03:30,060 --> 00:03:32,720
We actually have both the Next.js server

78
00:03:32,720 --> 00:03:35,713
and the Strapi server running on "localhost",

79
00:03:35,713 --> 00:03:37,243
but on different ports.

80
00:03:37,243 --> 00:03:39,437
Note that "localhost" here refers

81
00:03:39,437 --> 00:03:40,834
to the Strapi server,

82
00:03:40,834 --> 00:03:43,029
that's the source for the images.

83
00:03:43,862 --> 00:03:46,653
Anyway, if we save this file and reload the app

84
00:03:47,428 --> 00:03:48,825
it still doesn't work.

85
00:03:48,825 --> 00:03:51,938
That's because we need to restart the dev server.

86
00:03:51,938 --> 00:03:55,305
The configuration file is not automatically reloaded.

87
00:03:56,561 --> 00:03:58,200
And now it's working again.

88
00:03:58,700 --> 00:04:01,848
So it is now using the Next Image component

89
00:04:01,848 --> 00:04:03,239
to load the images.

90
00:04:03,813 --> 00:04:06,645
There's no obvious difference at first sight,

91
00:04:06,645 --> 00:04:08,597
the images still look the same.

92
00:04:09,160 --> 00:04:10,519
But if we look a bit deeper,

93
00:04:10,519 --> 00:04:12,655
with the help of the Chrome Developer Tools,

94
00:04:14,726 --> 00:04:16,707
we can see that for a start

95
00:04:16,707 --> 00:04:18,983
the images are now being loaded

96
00:04:18,983 --> 00:04:20,744
from the Next.js server,

97
00:04:20,744 --> 00:04:22,946
and not directly from the CMS.

98
00:04:22,946 --> 00:04:26,029
We can tell because the URL has port 3000.

99
00:04:26,823 --> 00:04:29,067
And it's from a special path

100
00:04:29,067 --> 00:04:31,553
that starts with "_next/image",

101
00:04:31,553 --> 00:04:34,118
and then the original image URL.

102
00:04:34,118 --> 00:04:37,084
That's what allows the Next.js server

103
00:04:37,084 --> 00:04:39,169
to act as a sort of proxy.

104
00:04:39,990 --> 00:04:42,109
If we look at the dimensions

105
00:04:42,109 --> 00:04:45,061
you can see that this time the image is

106
00:04:45,061 --> 00:04:46,423
640 by 480 pixels,

107
00:04:47,074 --> 00:04:50,232
which is smaller than the original image

108
00:04:50,232 --> 00:04:53,310
stored in the CMS, that was 960 by 720.

109
00:04:53,310 --> 00:04:56,625
Interestingly it's still twice as large as

110
00:04:56,625 --> 00:05:00,572
the dimensions we specified, that were 320 by 240.

111
00:05:00,572 --> 00:05:04,361
This is probably because I have a Retina display

112
00:05:04,361 --> 00:05:06,887
so it's using double resolution.

113
00:05:06,887 --> 00:05:09,255
But in any case, the image was

114
00:05:09,255 --> 00:05:12,491
definitely resized by the Next.js server.

115
00:05:13,543 --> 00:05:15,458
If we look at the network requests

116
00:05:15,458 --> 00:05:17,766
we can see some other interesting things.

117
00:05:18,322 --> 00:05:19,637
Let me reload the page,

118
00:05:19,637 --> 00:05:21,408
so it will re-fetch everything.

119
00:05:21,965 --> 00:05:23,966
One thing to notice is that

120
00:05:23,966 --> 00:05:26,337
the images are in "webp" format.

121
00:05:26,911 --> 00:05:31,261
If you remember, the image in the CMS was a JPEG.

122
00:05:31,261 --> 00:05:35,078
So the Next.js server converted it to WebP.

123
00:05:35,666 --> 00:05:37,857
The other interesting thing is

124
00:05:37,857 --> 00:05:40,486
that it only loaded 3 images so far,

125
00:05:40,486 --> 00:05:42,604
even though we know there are

126
00:05:42,604 --> 00:05:45,306
more than 3 products in our HomePage.

127
00:05:46,025 --> 00:05:48,747
That's because the Next Image component

128
00:05:48,747 --> 00:05:50,003
uses lazy loading,

129
00:05:50,003 --> 00:05:52,585
so it didn't load the images that are

130
00:05:52,585 --> 00:05:54,539
not yet visible on the page.

131
00:05:55,248 --> 00:05:58,546
If we scroll down, you can see that at some point

132
00:05:58,546 --> 00:06:00,161
it loads a fourth image,

133
00:06:00,728 --> 00:06:02,400
and as we keep scrolling,

134
00:06:02,400 --> 00:06:04,138
more images come into view

135
00:06:04,138 --> 00:06:06,077
and therefore will be loaded.

136
00:06:06,711 --> 00:06:09,134
That's a great optimization technique,

137
00:06:09,134 --> 00:06:11,494
especially on a page such as this one

138
00:06:11,494 --> 00:06:13,855
where we have lots of product images,

139
00:06:13,855 --> 00:06:16,980
but only a few of them will be initially visible.

140
00:06:17,672 --> 00:06:20,413
Ok. So that's another nifty little feature

141
00:06:20,413 --> 00:06:23,088
we get for very little effort in our app.

142
00:06:24,105 --> 00:06:27,010
The final thing I want to show you is that

143
00:06:27,010 --> 00:06:30,468
the Next.js server will cache the generated images

144
00:06:30,468 --> 00:06:32,889
somewhere under the ".next" folder.

145
00:06:33,528 --> 00:06:36,299
So when the same image is requested again

146
00:06:36,299 --> 00:06:39,409
the server will simply return the cached file.

147
00:06:39,977 --> 00:06:42,617
It's not something we need to worry about

148
00:06:42,617 --> 00:06:45,450
because Next.js does all that automatically,

149
00:06:45,450 --> 00:06:46,867
but it's good to know.

150
00:06:47,496 --> 00:06:49,858
So this how we can take advantage

151
00:06:49,858 --> 00:06:52,578
of all the image optimization features

152
00:06:52,578 --> 00:06:54,010
provided by Next.js.

153
00:06:54,010 --> 00:06:56,516
Simply use the Next Image component

154
00:06:56,516 --> 00:06:59,093
instead of the standard HTML element

155
00:06:59,093 --> 00:07:01,241
whenever we display a picture,

156
00:07:02,099 --> 00:07:05,275
and Next.js takes care of all the rest for us.

