August 6, 2021 Link to lesson

Improving Web Performance using the Image Service CDN

In this lesson, you will learn how to improve your app's or website's performance by utilizing the Storyblok image transformation API. We'll explore the differences and advantages of using a CDN image service versus not. Once we have implemented the transformation service, we'll compare web performance metrics with and without the CDN.

Storyblok Image CDN diagram
Uploaded image directly served vs Optimized Image served Flow

1st Example - Original image

Rendering the uploaded image directly without resizing or reformatting it.

Problems

  • The image is not appropriately sized, not saving cellular data and getting worse load time.

  • Not encoded effectively, causing it to load slowly and consume more mobile data.

  • May not be served in NEXT-GEN formats, providing worse compression.

  • The image tries to be loaded before critical resources instead of being lazy loaded, increasing the interactivity time.

Solutions

Example of an image not resized or formatted
Image not resized or formatted Photo by Alyani Yang on Unsplash

2nd Example - Resized and formatted image

Images uploaded to Storyblok are automatically available through its image CDN. This CDN service allows us to transform, resize and modify the images by changing the URL parameters.

Options

  • Size: <width>x<height>

  • Filters:

    • format(<extension>)

    • fill(<color>)

    • quality(<0-100>)

  • Smart crop: /smart

Tip

As we use the Storyblok Image CDN, preconnecting to it can improve the images load time <link rel="preconnect" href="//img2.storyblok.com">

Example of image resized and formatted with the storyblok image service CDN
Image resized and formatted with the Storyblok Image CDN By Unsplash
  
    
// Method to resize and format an image
transformImage(image, option) {
  if (!image) return '';
  if (!option) return image;
 
  const imageService = '//img2.storyblok.com/';
  let path = image.replace('https://a.storyblok.com', '');
  path = path.replace('//a.storyblok.com', '');
  let format = ''
  if (process.client) {
    format = !this.canUseWebP() ? '' : '/filters:format(webp)'
  }
  return imageService + option + format + path;
}

// Method to detect if webp can be use or not
canUseWebP() {
  if (window.canUseWebP) return window.canUseWebP;

  const el = document.createElement('canvas');
  if (el.getContext && el.getContext('2d')) {
    window.canUseWebP = el.toDataURL('image/webp').indexOf('data:image/webp') === 0;
    return window.canUseWebP;
  }

  window.canUseWebP = false;
  return window.canUseWebP;
},