
Let’s talk about Image Optimization with Next.js - Saad Irfan - (Next.js Conf 2021)
Let’s talk about Image Optimization with Next.js - Saad Irfan - (Next.js Conf 2021)
Because of their size, images are the largest assets of your website. As the size increases, the speed of your web app decreases along with it. According to the HTTP Archive, images make up on average 21% of a total webpage weight. Different image formats also affect your site’s overall performance. In this talk, I am going to speak about how Next.js natively helps you optimize your images. How it provides a built-in solution with its Image component that uses various techniques to make sure your site is fast, consumes less bandwidth, and at the same time has a great user experience.
Saad Irfan
Student Expert at RapidAPI
Content
4.879 -> - Hello, everyone.
6.05 -> I am Saad.
6.883 -> And today I'm going to talk
about the elephant in the room,
9.46 -> a particular asset of your
website that is responsible
12.07 -> for making it either slow
and crappy or super fast.
15.49 -> Yeah.
16.323 -> I'm talking about no other than images
17.88 -> and how if they're not optimized,
19.46 -> your sites performance
literally goes to hell.
22.1 -> So before I begin, let
me introduce myself.
24.35 -> My name is Saad. I am a
senior year computer science,
26.89 -> undergrad student,
27.79 -> currently working as a
student expert at rapid API.
31.01 -> I'm a huge fan of what
open source stands for,
33.74 -> and I love building open source softwares.
35.88 -> In fact,
36.713 -> I have personally authored
20 plus open source tools
39.25 -> that are used by thousands
of developers out there.
41.75 -> I love giving back to my community.
43.69 -> My love for it took me to
get accepted into different
46.63 -> community-based programs
at Google and Microsoft,
49.55 -> if you want to reach out to me,
50.91 -> I am most active on my Twitter
52.42 -> and you should also definitely
54.07 -> follow me there.
54.903 -> So now,
55.736 -> let's talk about image optimization.
57.41 -> I have built this small demo using next.js
59.92 -> with simple HTML image tag,
61.81 -> and then the image component of next.js.
64.75 -> In using this demo,
65.85 -> I'm going to show you how
the simple image tag works.
68.8 -> What are some of the disadvantages
of using the image tag?
71.828 -> And I am also going to
show you the, you know,
75.2 -> working off the image component of next.js
78.03 -> and some of the advantages
79.47 -> of using the image component or image tag.
82.66 -> So without any further ado, let's jump in.
85.05 -> So I'm going to click
on this image button.
87.26 -> It is going to take me to another page
89.13 -> where I am loading a bunch of images
91.11 -> using simple image, HTML tag.
93.54 -> So I'm going to click on it and see
96.86 -> that there are a bunch of images in here.
100.16 -> They are being loaded on
the screen, by the way,
102.72 -> all of these images are
being taken from unsplash.com
105.6 -> if you want to visit.
107.35 -> So I'm going to go back up there.
109.37 -> So there is how it works button.
I'm going to click on it.
113.07 -> It is going to take me to this page.
114.77 -> So let's take a look at the
inner working of image tag.
117.21 -> You define the source and
alt attributes of image tag,
120.54 -> the client requests the
server for the image
122.92 -> using their provided source.
124.79 -> The server sends back the
image in its original format.
127.81 -> For example, if the image is a JPEG,
130.3 -> it is going to send back a JPEG.
132.09 -> If it is a PNG, it is
going to send back a PNG.
135.3 -> The image tag then renders the image
137.28 -> with its original size
138.59 -> It is not going to take into
account the user's browser
141.63 -> or the user's view port.
143.39 -> If the user is on a mobile device,
144.98 -> it is still going to load the same image.
146.69 -> So this is how it works.
148.04 -> Let's take a look at some
cons of using the image tag
152.21 -> and the server requests,
all images at once.
155.66 -> What does that mean is that for instance,
157.93 -> you have an image at the
very bottom of the page.
160.65 -> And do you have just loaded
the website and the images,
163.615 -> image is at the bottom,
165.14 -> and you don't necessarily
want to go to the bottom
168.36 -> of the page here.
169.193 -> The image is still being
loaded on the screen.
172.76 -> The client has still requested
the server for that image.
175.78 -> Even if you don't go to the
bottom, let me show you.
178.26 -> If I just go back here,
179.8 -> go back to this area and
open the developer tools.
183.72 -> Let's go to the networks tab.
186.69 -> You see.
187.64 -> Now I'm going to hard reset this page
190.4 -> and you will see a lot of requests here.
193.32 -> And all of these requests
will be related to getting the
195.92 -> images from the server.
199.06 -> You see, there are a lot of requests here.
201.22 -> Some of them have been successful.
202.82 -> Some of them are still pending, but yeah,
205.78 -> there are a lot of requests in here,
207.75 -> even at the image that is at
the very bottom of the screen
211.52 -> is being, you know,
requested from the server.
214.25 -> Even if I don't want to
go to the very bottom,
216.75 -> it is still being
requested from the server.
218.74 -> So it is actually
wasting user's bandwidth.
221.15 -> And it is also at the same
time decreasing the site's
223.807 -> performance because all of
the images are being loaded,
227.495 -> being requested from the
server, which is sure,
230.57 -> which should not be the case
because let's say the user
233.04 -> don't want to see the very
last image on the screen.
236.07 -> So this is one of the
problems with this image tag.
238.86 -> So let's close this and
go to how it works again,
241.99 -> but let's go to the
bottom of the page again.
243.72 -> And you see,
244.845 -> there is no lazy loading
with simple HTML image tag.
247.346 -> What it means is that
client should request server
249.941 -> for an image as soon as
it is about to appear
252.327 -> on the view port.
253.343 -> It shouldn't request for
images. All the images at once.
256.298 -> This issue is basically
related to the first one.
258.547 -> So yeah,
259.38 -> there is no lazy loading
with simple HTML image tag.
262.44 -> And now,
263.273 -> Let's take a look at the last
one, layout shift occurs.
265.62 -> So this is actually
cumulative layout shift
267.78 -> that occurs with simple HTML image tag.
270.76 -> So what happens is let's
say you have a huge image
273.042 -> in your website,
274.63 -> and the image is in the
middle of some content.
277.12 -> When the image is loading,
278.14 -> the content is going
to appear side by side.
279.815 -> As soon as the image appears,
281.74 -> the content is going to
move it from each other.
283.83 -> So this is called cumulative layout shift.
286.08 -> And you know,
286.933 -> this is one of the issues that arises
289.31 -> with using simple HTML image tag.
291.34 -> So this is the image tag.
292.72 -> Some of the issues that we saw was
294.48 -> there was no lazy loading,
296.3 -> the server requests all
the images are ones.
298.5 -> Even if the user doesn't even, you know,
300.62 -> maybe don't even need those images.
302.33 -> There is cumulative
layout shift that occurs,
304.733 -> when using the simple HTML tag.
307.31 -> So now let's go back to the
homepage and talk about the
312.362 -> image component of next.js.
315.08 -> So I'm going to click on
this image button here.
317.86 -> It is going to take me to another page
319.66 -> where I am loading a bunch of images
321.5 -> using the image component of next.js
323.84 -> So let's do that.
325.84 -> You see this image is blurred.
327.95 -> I'm going to tell you about
this later, why it is blurred.
332.23 -> Almost all of them are blurred right now.
336.35 -> If I go back up there,
340.45 -> you will see that this
image has been loaded
342.68 -> and this one as well, this one as well.
345.18 -> And now if I go down,
347.05 -> almost all the images have been loaded.
348.86 -> Some of them are,
349.693 -> still haven't been loaded
and they are still blurred.
352.51 -> I'm going to tell you
about why they are blurred
354.54 -> a little later.
355.71 -> So let's go to this, how it works.
358.57 -> So let's take a look
359.403 -> at how you can use image
competent in next.js.
361.91 -> You provide the image
component with the source
364.31 -> and alternate text a width
and a height of the image.
368.29 -> The client then requests
the server for the image,
370.73 -> using the provider tools.
372.45 -> The server sends back the
image with webP format.
375.34 -> The image component then renders the image
377.84 -> according to the view port.
379.25 -> Let's take a look at the
component in, you know in action.
382 -> So I have this cord here.
384.66 -> So by the way, this is the
cord for this, you know,
387.36 -> this application you are seeing.
388.87 -> So this is the image component.
391.38 -> I have a source and
alternate text are quality.
395.17 -> I'm going to tell you about this later.
397.42 -> Then there is width, height.
398.97 -> And then again,
399.88 -> I'm going to tell you about
these two as well, you know,
402.41 -> a little later, but these are placeholder,
404.97 -> and blur data URL and yeah.
407.2 -> So let's go back and scroll
down to take a look at the pros.
410.76 -> So the first thing that you
will see is that next.js
413.984 -> optimizes image by adding source set.
417.09 -> So what is source set?
418.59 -> So, you know, earlier I talked about how,
421.92 -> you know, the image tag doesn't care about
424.442 -> what the view port of the user is.
427.11 -> It just gives the image
in its original size.
430.01 -> Next.js doesn't do that.
431.85 -> The image component of
next.js automatically adds
434.737 -> the source set. Even if you
haven't added it yourself.
437.95 -> So let's take a look. So let's
go back to the previous page.
441.56 -> I am going to then inspect
this picture and you will see
447.316 -> that I have a source set attribute here.
450.4 -> I haven't added this attribute myself.
452.7 -> Next.js has automatically added this using
454.97 -> the image component. I can even show you.
457.77 -> You see, I don't have
any source set attribute.
460.4 -> I have just source attribute here.
462.53 -> So if I just go back and
I'm going to show you
465.498 -> one other thing as well.
466.78 -> So you can see that I have
a file size of 16.3 Kb.
472.1 -> And you know,
473.46 -> if I just show you the
size of the original image,
476.27 -> it is full 446 kb.
478.7 -> It's like 500 kb image.
And it's been, you know,
481.84 -> optimized to 16.3 kb using next.js.
485.39 -> So what does this also do?
486.74 -> It actually renders different size images
488.93 -> based on the device pixel ratio
490.69 -> of whatever device you're using
492.31 -> to see the application.
493.33 -> Let's say you are on a laptop.
494.99 -> Then in that case, it is going
to render a larger image.
497.95 -> Let's say you are now on a mobile device.
499.73 -> It is going to render a smaller image now.
501.56 -> So it is actually optimizing images
504.18 -> based on different screen sizes
505.97 -> and different screen resolutions.
507.39 -> So let's close this now
and go back to how it works
510.72 -> scroll down.
511.553 -> So let's take a look at
the second advantage.
513.81 -> Now, next.js' image
component serves WebP format.
517.83 -> If I scroll up,
518.77 -> you will see that I have
written the server sends back
521.524 -> the image with WebP format.
523.84 -> So what is this format?
524.91 -> It is actually the
recommended image format
527.64 -> that you should use in your website.
529.97 -> Google states that WebP typically achieves
532.54 -> an average of 30% more compression
534.94 -> than JPEG and JPEG 2000.
536.94 -> Without loss of image quality, and Apple,
539.01 -> has also recently added
the WebP format support
541.91 -> in the safari browser last year.
543.46 -> Let me show you how to
server is sending you
545.51 -> this WebP format.
546.44 -> Let's go back to the previous page,
548.84 -> open the developer tools
here, go to the networks tab.
552.55 -> Now, if you scroll down,
553.81 -> you will see images are being
requested from the server
557.34 -> and the type of them are WebP.
560.08 -> So let's close this and go back up here
563.67 -> and go to how it works
page and scroll down.
567.08 -> So the next thing is
next.js image component
570.03 -> prevents cumulative layout shift.
571.78 -> Earlier, I explained to you
573.43 -> what cumulative layout shift is.
575.08 -> And with next.js image
component, you can prevent this.
577.84 -> What happens is if you're using
a next.js image component,
581.05 -> the content is not going to
be appeared side by side.
583.65 -> In fact, it will have
a space for the image
585.61 -> where the image will come
587.61 -> as soon as it renders on the screen.
589.31 -> So the next one we have is lazy loading.
591.48 -> What is it? Let's take a look.
593.62 -> I'm going to go back to the previous page.
595.78 -> So I'm going to hard reload this page now,
600.295 -> and you see that this is now blurred.
603.07 -> Now I'm going to inspect
element on this page,
606.61 -> go to the networks tab and now,
609.243 -> if I just scroll down
611.13 -> as this image appears in
the view port, you will,
613.56 -> you can see that the client
614.81 -> has request a server for this image.
617.56 -> You can see it's pending right now.
621.3 -> And now if I, again, scroll down,
623.96 -> you can see that client
has again requested server
626.61 -> for another image. And again, scroll down,
631.343 -> as I'm scrolling down,
632.176 -> the client is requesting
servers for more images.
636.96 -> If I scroll, go back up,
638.4 -> you can see that with images 200 status
641.68 -> have been rendered on the screen.
644.2 -> So this is actually lazy loading.
645.72 -> The client has not, you know,
647.79 -> requested all the images
at once from the server.
650.65 -> In fact, as soon as the
image is about to appear at,
653.263 -> in the view port, the client is, you know,
656.49 -> requesting that image.
658.69 -> You can see all of these
are at 200 status and all,
663.99 -> if I go down,
666.08 -> there are more images
that are being requested
669.63 -> from the server.
672.31 -> And yeah, you can see that.
674.15 -> So this is actually what lazy loading is,
676.91 -> and it greatly affects the
performance of your application.
680.207 -> And one more thing that I should add
681.77 -> is if you want an image
to appear instantly,
684.29 -> as soon as the website loads,
686.05 -> you can also do that
with the image component.
687.98 -> All you need to do is
provide the loading prop
690.685 -> and set its value to eager,
692.79 -> and you will have an image instantly load
695.18 -> as soon as the website load.
696.75 -> So let's now close this and
go back to how it works.
701.03 -> So now let's take a look
at another advantage.
703.4 -> So with next.js image component,
705.209 -> you have built-in
responsiveness in your images,
707.28 -> lets take a look at what it means.
708.81 -> I'm going to go to the previous page.
710.61 -> And now again, I'm going to
inspect element this page.
714.3 -> Let's, you know, select this option.
717.03 -> And from here, let's go with responsive.
720.251 -> If I show you now, what
happens is, you know,
723.929 -> when I have a wider
screen, I have this image.
728.46 -> And as soon as the screen gets small,
731.32 -> the size of the image
changes along with it.
734.45 -> So this is built in responsiveness
736.16 -> in next.js image component.
737.69 -> And you can also take a look
that I have not added anything
740.16 -> in next.js image component that is related
742.64 -> to responsiveness and it
is handling this itself.
745.78 -> So now let's close this and
go to how it works page again.
749.726 -> So the next thing we have
is place holder prop option.
752.92 -> Earlier,
753.753 -> I said that I am going to tell you about
755.63 -> that blurry effect later, and this is it.
758.356 -> If you go back and if I
hard reload this page,
763.363 -> you will see that there is
this blurry effect here.
766.71 -> What's happening is right
now, the client has requested
769.59 -> server for this particular image.
771.2 -> And while it is waiting for the server
773.04 -> to give it back a response,
774.52 -> it is actually adding a place holder.
776.83 -> And I'm using that particular
image that is being requested
780.53 -> from the server as a placeholder as well.
782.14 -> So it's being rendered on the screen
784.38 -> and you can see if I
just scroll down there.
786.96 -> There are some blurry pictures
and they are just being,
790.63 -> you know, rendered on the
screen with the original images.
793.74 -> Let's take a look
794.59 -> at how you can do this in
your next.js application.
797.04 -> So I have this image component here.
800.391 -> What I need to do is now I have
to add this placeholder prop
805.13 -> and give it the value of blur.
807.11 -> And the next thing is,
808.43 -> you need to give it a blurred data URL.
810.814 -> It is going to take the URL
of the image that you want
813.74 -> in place of the, you know, placeholder.
816.29 -> So you need to give it
the URL of that image.
818.504 -> So now let's go back to the
how it works page. scroll down,
822.23 -> and so we have the last one,
824.25 -> that with next.js image component,
826.23 -> you can set the image quality of an image.
828.89 -> The default image quality is 75.
831.29 -> Like if you are not
setting the image quality,
833.2 -> it is going to be 75.
834.54 -> For any image that you insert,
836.63 -> the range is actually one to a hundred
838.07 -> and you can select any of the
numbers between this range
840.94 -> and the next.js is going
to automatically, you know,
843.79 -> optimize your image
according to that number.
846.38 -> So this is it, folks. I
hope you like this talk.
848.85 -> And now, you know, the difference
849.95 -> between the image tag
and the image component
851.9 -> of next.js.
852.86 -> And now you're going to
use the image component
854.7 -> of next.js to make your websites
856.34 -> even faster than they are right now.
858.05 -> I'm going to share the
link of this small demo
860.08 -> that I created on my twitter.
861.62 -> So if you're not following me there,
863.07 -> you should definitely follow me.
864.78 -> I think that is pretty much
it until next time. See ya.
868.316 -> (upbeat electronic music plays)
Source: https://www.youtube.com/watch?v=6EOZf-FOUDI