One of my favorites quotes is from Steve Job’s biography by Walter Isaacson.

“If it could save a person’s life, would you find a way to shave ten seconds off the boot time?” he asked. Kenyon allowed that he probably could. Jobs went to a whiteboard and showed that if there were five million people using the Mac, and it took ten seconds extra to turn it on every day, that added up to three hundred million or so hours per year that people would save, which was the equivalent of at least one hundred lifetimes saved per year.”

Isn’t that wonderful to think about? Only a bit of effort can save so much time. This is a philosophy I apply to everything I do. From trying to save seconds from typing to decreasing load speeds on my projects, I try to make things as quick and fast-moving as possible.

I used this mindset when developing my photo website by employing different methods. Even though five million people aren’t visiting my site, it’s important to me that the site provides the best experience possible.

Mobile PageSpeed Insights

Desktop PageSpeed Insights

It’s taken me a long time before reaching anywhere near these speeds. I’ve been developing this site for about five years now, and it started out with a score of about 30. So, how did I improve its performance by so much?

WebP Image Format

WebP is a new image format by Google developed for the web. It works on all Chromium browsers, and its load speeds are crazy fast. It minimizes file size while retaining quality. Whenever possible, I load WebP images. In fact, the only case I don’t load them is if if the browser doesn’t support it (@Safari).

Thumbnails

The first place any user will see pictures is thumbnails. Here, this is easy for me to display either WebP or JPG - I use the <picture> tag. It allows me to give different image sources and identify a fallback <img> tag in case none work. This supports all browsers without me having to do anything specific.

1
2
3
4
5
<picture>
  <source type="image/webp" srcset="image.webp" />
  <source type="image/jpeg" srcset="image.jpg" />
  <img src="image.jpg" />
</picture>

This makes my life easy, as I simply render each thumbnail with a <picture> tag and put in the corresponding paths to the WebP and JPG version.

Expanded Images

The second place I show the images is if the user clicks on a thumbnail to view the photo. Adding WebP support for this feature was tricky. The gallery library I use, Magnific Popup, allows clicking of the thumbnail by wrapping it in an <a> tag. This means that the href for that tag can only be a single path to one of the images.

So by default, I keep all the paths to the JPGs. But in the background, I use a library called Modernizr to detect if the browser supports WebP. If it does, then I iterate over these links and set the image source to the WebP file. The only drawback is if the user opens one quickly, then it’s possible that a user may expand the full JPG image. However, I’ve never found this to occur when testing.

Responsive Images

Another feature that I have leveraged to decrease loading time is by serving responsive images. The idea of this feature is to serve the smallest possible image needed based on screen size and display density. I only use this for thumbnails – detecting which image to serve manually is too difficult. The preloading gallery feature works well enough so that a user should only have to wait for a single image to load anyways. If its WebP, it especially doesn’t take long.

For the responsive thumbnails, I support 4 different sizes: 400px, 600px, 800px, and 1024px. The browser should then decide which to serve. This saves time by loading smaller images when possible, also using less data. To do this, I again take advantage of the <picture> tag and the different <source>s inside of them.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<picture>
  <source
    type="image/webp"
    sizes="(max-width: 760px) 90vw, (max-width: 1300px) 40vw, 500px"
    srcset="
      image-400w.webp  400w,
      image-600w.webp  600w,
      image-800w.webp  800w,
      image.webp      1024w
    "
  />
  <source
    type="image/jpeg"
    sizes="(max-width: 760px) 90vw, (max-width: 1300px) 40vw, 500px"
    srcset="
      image-400w.jpg  400w,
      image-600w.jpg  600w,
      image-800w.jpg  800w,
      image.jpg      1024w
    "
  />
  <img src="image.jpg" />
</picture>

Script

I wrote a bash script to generate all file types and different sizes for all images in a specific directory. It converts all expanded size images into WebP, and all thumbnails into 3 more sizes of both WebP and JPG.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
for i in $(seq 0 $COUNT)
   do
      cwebp "$DIR"/img/"$FILE_NAME"_"$i".jpg -o "$DIR"/img/"$FILE_NAME"_"$i".webp
      cwebp "$DIR"/thmb/"$FILE_NAME"_"$i".jpg -o "$DIR"/thmb/"$FILE_NAME"_"$i".webp
      for j in "${DIM[@]}"
         do
            convert "$DIR"/thmb/"$FILE_NAME"_"$i".jpg -resize "$j" "$DIR"/thmb/"$FILE_NAME"_"$i"-"$j"w.jpg
            cwebp "$DIR"/thmb/"$FILE_NAME"_"$i"-"$j"w.jpg -o "$DIR"/thmb/"$FILE_NAME"_"$i"-"$j"w.webp
         done
   done