Skip to content

Commit

Permalink
Feat: adds LazyLoadingSection component - perf (#2521)
Browse files Browse the repository at this point in the history
## What's the purpose of this pull request?

Adds `LazyLoadingSection` component, it will be responsible for lazy
loading Sections that are out of the viewport.
 * It achieves this by:
 * 1. Using the IntersectionObserver API for Sections below the fold.
* 2. Checking the UI context for Sections that are not in the viewport,
such as the CartSidebar and RegionModal.

We will be implementing this in the `RenderSectionsBase` as part of our
upcoming tasks. This component is not being applied in isolation due to
concerns about increased Cumulative Layout Shift (CLS).

## How to test it?

1. You can use this [preview
link](https://starter-git-feat-lazy-loading-section-sfs-1508-faststore.vercel.app/),
where the `LazyLoadingSection` is temporary applied or locally add it in
`RenderSectionsBase` component.

``` 
 <SectionBoundary key={`cms-section-${name}-${index}`} name={name}>
      <LazyLoadingSection sectionName={name}>
           <Component {...data} />
      </LazyLoadingSection>
 </SectionBoundary>

```

2. Inspect the code, use the React extension for this test:
- search for `Footer`, you won't find it until you scroll the page until
the `Newsletter` section
<img width="1144" alt="image"
src="https://github.com/user-attachments/assets/46e2eca0-1ce3-473c-9153-29ddb731881a">

<img width="1164" alt="image"
src="https://github.com/user-attachments/assets/3132efca-38c5-4e41-b8e2-ea69b2adbf9e">



https://github.com/user-attachments/assets/bbfffbe0-39b8-4b6b-b86d-04d4a7ab1e6b


### Starters Deploy Preview
vtex-sites/starter.store#586

## References
#2404

---------

Co-authored-by: Pedro Soares <32311264+pedromtec@users.noreply.github.com>
  • Loading branch information
hellofanny and pedromtec authored Oct 28, 2024
1 parent 180d1b1 commit 04d045d
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 3 deletions.
50 changes: 47 additions & 3 deletions packages/core/src/components/cms/RenderSections.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import { ComponentType, PropsWithChildren, memo, useMemo } from 'react'
import {
ComponentType,
PropsWithChildren,
ReactNode,
memo,
useMemo,
} from 'react'

import SectionBoundary from './SectionBoundary'
import { Section } from '@vtex/client-cms'
import SectionBoundary from './SectionBoundary'
import ViewportObserver from './ViewportObserver'

import { useUI } from '@faststore/ui'

interface Props {
components: Record<string, ComponentType<any>>
sections: Array<{ name: string; data: any }>
}

const SECTIONS_OUT_OF_VIEWPORT = ['CartSidebar', 'RegionModal']

const useDividedSections = (sections: Section[]) => {
return useMemo(() => {
const indexChildren = sections.findIndex(({ name }) => name === 'Children')
Expand All @@ -21,6 +32,39 @@ const useDividedSections = (sections: Section[]) => {
}, [sections])
}

/**
* This component is responsible for lazy loading Sections that are out of the viewport.
* It achieves this by:
* 1. Using the IntersectionObserver API for Sections below the fold.
* 2. Checking the UI context for Sections that are not in the viewport, such as the CartSidebar and RegionModal.
*
* @param sectionName
* @returns
*/
export const LazyLoadingSection = ({
sectionName,
children,
}: {
sectionName: string
children: ReactNode
}) => {
const { cart: displayCart, modal: displayModal } = useUI()

if (SECTIONS_OUT_OF_VIEWPORT.includes(sectionName)) {
const shouldLoad =
(sectionName === 'CartSidebar' && displayCart) ||
(sectionName === 'RegionModal' && displayModal)
if (!shouldLoad) {
return null
}

return children
}
return (
<ViewportObserver sectionName={sectionName}>{children}</ViewportObserver>
)
}

const RenderSectionsBase = ({ sections = [], components }: Props) => {
return (
<>
Expand All @@ -37,7 +81,7 @@ const RenderSectionsBase = ({ sections = [], components }: Props) => {
}

return (
<SectionBoundary key={`cms-section-${index}`} name={name}>
<SectionBoundary key={`cms-section-${name}-${index}`} name={name}>
<Component {...data} />
</SectionBoundary>
)
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/components/sections/Hero/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ const Hero = ({
width={360}
height={240}
sizes="(max-width: 412px) 40vw, (max-width: 768px) 90vw, 50vw"
priority={true}
/>
</HeroImage.Component>
<HeroHeader.Component
Expand Down

0 comments on commit 04d045d

Please sign in to comment.