Best Practices

🚧

Important note

Make sure to read the accessibility best practices as well.

Images

  • Always use ResponsiveImage.
  • Use sizes to help browsers load the image in a proper size.
  • Set the width and height to the image to avoid Cumulative Layout Shift (CLS). Another resource here.
    • Images coming from variables inside Shogun Frontend have width and height sent in the media object. See example below:
import React from 'react'
import ResponsiveImage from 'frontend-ui/ResponsiveImage'

const SomeComponent = ({ image }) => (
  <ResponsiveImage
    src={image.src}
    alt="A black t-shirt with a black Shogun logo on it. The t-shirt is on a red surface."
    sizes="(max-width: 767px) 80vw, 40vw"
    width={image.width}
    height={image.height}
   />
)

export default SomeComponent
  • If the image is within the viewport, set loading="eager".

Server side vs. client side

PWAs renders your store on the server side, hence the name SSR (Server Side Rendering). This technique allows your store to be blazing fast, but, mind your code. If you need to use some code that relies on client side APIs, such as window and/or document, do so inside of an useEffect hook:

import React from 'react'

const MyComponent = () => {
  React.useEffect(() => {
    const someElement = document.querySelector('.some-class')
  })

  return <p>My component.</p>
}

export default MyComponent

Guard clauses

When accessing object properties, make sure the parent property exists. For example, when mapping through an array of images, check if the array empty before mapping through its item.

import React from 'react'
import ResponsiveImage from 'frontend-ui/ResponsiveImage'

const ProductBox = ({ product }) => {
  const { media } = product || {}
    
  // do not render the component
  // if media array is empty
  if (media.length === 0) return

  return (
    <section className="ProductBox">
      <h1>ProductBox</h1>
      {media.map(img => (
        <div key={img.id}>
          <ResponsiveImage
            src={img.src}
            alt=""
            sizes="(max-width: 767px) 80vw, 40vw"
            width={img.width}
            height={img.height}
           />
        </div>
      ))}
    </section>
  )
}

export default ProductBox

CSS classes

For conditional classes, we recommend the classnames npm package. Contact support to install it into your store if needed.

Naming conventions

Below are some naming conventions recommendations. It's up to you and your team decide a naming convention, and above all, consistency is the key.

  • We recommend using PascalCase for naming your components and sections.
  • Consider using SUIT CSS for CSS classes
  • Prefer descriptive variables names like productImage instead of img (unless the variable context allows for clarity).
  • VariablesVariables - In the context of Shogun Frontend, variables are the props passed to the Sections. These are defined in the right sidebar in the IDE. These variables will be available when editing one of your pages, allowing you to map them to a field in the CMS or manually enter the values directly in the Experience Manager sidebar. names must follow the camelCase convention.

Unused variables

To avoid increase in the store's build and publish process, double check if all the variables selected in the IDEIDE - Integrated Development Environment. for a section are actually in use within the code.

Fonts

  • Inline external fonts to avoid resource chain.
  • Apply font-display: swap to any external font-face rule.
  • If using Google Fonts, make sure your font url has &display=swap on it.

Buttons

  • A button should be used to trigger an action, for example: submit a form. A link is not a button.
  • Use the <button> tag instead of <div className="button">.

Links

Instead of using a normal a tag, use Shogun Frontend Link.

For external links add:

Videos

Use the Video Component to lazy load videos by setting loading="lazy". If the video is on the viewport, use loading="eager".

Iframes

When possible, lazy load iframes with loading="lazy".

Performance

  • Load third-party scripts integrations from the App component.
  • Preconnect common used hosts
    • https://fonts.googleapis.com if using Google fonts
<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin />

Did this page help you?