React Storefront
|

Optimizing Performance

Measuring Performance Using Lighthouse

It is important to record performance measurements before and after making changes to the codebase.

One of the best ways to do this is by using Chrome's Lighthouse Audit Tool. It is important to note that running Lighthouse against local development will yield significantly lower performance scores than production due to the lack of caching in development.

Use incognito mode to prevent possible issues with Chrome extensions and other potential oddities while measuring.

Image Optimization

An application's lighthouse score can often be significantly improved by optimizing how Images are loaded. On mobile devices, images should be downscaled to conserve bandwidth and served in webp format when supported by the browser. Moovweb's XDN and React Storefront make it easy to do this.

Image Component

To display individual images as React components, use React Storefront's Image React component. You can downscale the image using the quality prop, with takes a number from 1 to 100 corresponding to the percent the image should be downscaled. You can also use the lazy to delay loading the image until it is visible in the viewport. Here's an example:

import Image from 'react-storefront/Image'

export default Component({ image }) {
  return <Image src={image} quality={80} lazy />
}

Images within CMS content

React Storefront provides the following functions to help optimize images found in HTML stored in your CMS:

optimizeImages(options)

Transform images using Moovweb's CDN with the following options:

  • quality A number or string containing the number for the desired quality, on a scale from 1 (worst) to 100 (best).
  • width A number or string containing the number for the desired pixel width.
  • height A number or string containing the number for the desired pixel height.
  • format A string containing the desired file format. Options include jpg, png, and webp.
  • sourceAttributes An array of the attributes which contain the image source.
  • preventLayoutInstability Wrap the image in a container which fills the aspect ratio of the original image.

lazyLoadImages()

Delays the loading of each image until it is visible in the viewport. You must set CmsSlot's lazyLoadImages prop in order to use this feature.

Example Usage

import parse from 'react-storefront-extensions/html/parse'

export default somePageHandler(params, request) {
  const html = await fetchUpstreamHtml()
  const $ = parse(html)
  $('img').optimizeImages({ quality: 80 })
  $('img').lazyLoadImages()
  return {
    content: $('.content').html()
  }
}

Tip: There are situations where alternative attributes are used for image sources, such as data-src. You can specify those attributes in the options of optimizeImages using the sourceAttributes prop.

$('img').optimizeImages({ width: 500, sourceAttributes: ['src', 'data-src'] })

Lazy Loading Components

Components displayed below the fold that are resource intensive, such as third-party JavaScript widgets, should be loaded only when the user scrolls them into view. You can lazy-load any component by wrapping it in React Storefront's Lazy component:

It is important to set an explicit height for lazy components to prevent layout instability when the component is loaded. This can be done using style or className.

import Lazy from 'react-storefront/Lazy'

export default BelowTheFold() {
  return <Lazy style={{ height: 500 }}>
    <Contents />
  </Lazy>
}

Check AJAX response sizes.

When requesting data for a server side AJAX handler, make sure to reduce the size of the response as much as possible. The response size should be in the 10-30k range. Definitely not 100k+. Only respond with data the client will specifically need.

Use Preconnect

Make sure any domains which resources will be requested from use the preconnect hint. Preconnect allows the browser to setup early connections before an HTTP request is actually sent to the server.

<link href="https://cdn.domain.com" rel="preconnect" crossorigin />

Analytics Optimization

When using any analytics targets, it is important to use the delayUntilInteractive prop in the AnalyticsProvider. This allows the browser to focus on fetching the required resources first, then after the page becomes interactive, the targets are loaded.