---
# System prepended metadata

title: Carousel Optimisations

---

---
title: Carousel Optimisations
description: View the slide with "Slide Mode".
slideOptions:
  theme: solarized
  transition: 'slide'
type: slide
---

<style>
.reveal {
  font-size: 24px;
}
</style>

# Carousel optimisations
:carousel_horse: :carousel_horse: :carousel_horse: 

---

## Issues
:thinking_face:

----

The performance of the new navigation pages using the slider component was poor with long load times
![](https://i.imgur.com/2ozYi1E.png =550x)


----

### The way content data was fetched from Contentful was suboptimal

- 4 levels of nesting were fetched. That's an enormous payload containing all the fields for articles, events, Q&A, etc
- Most of the content data downloaded were not used at all to populate the UI

**Before:**  620 Kb were downloaded for 2 sliders and 13 cards
**After:** Only 5 Kb are downloaded

----

### The data parsing was blocking the rendering of the whole Slider component

- After fetching the content data from Contentful, a 1st loop was done to modify multiple content entries
- After that, a 2nd loop was required to fetch user-related data from the People API for each card if needed
- Finally, an additional layer of data parsing was executed at the Slider Card itself

**Before:**  Users didn't see anything on the screen until data parsing was completed
**After:** Each card loads independently and only one loop to render the cards

----

### Unnecessary use of expensive dependencies and CPU-intensive functions

- The Slider was using `md5` and `react-uuid` dependencies to generate internal React keys
- At the Slider Card's data parsing, the "reading time" was computed on page load based on the body of the article

**Before:** The cost associated with running CPU-intensive functions was dragging down the performance
**After:** Fewer CPU-intensive functions when loading card

---

## Optimisations
:hammer_and_wrench: 

----

### Contentful

**New `Carousel` content model**

- Similar to existing `Slider` content model
- New `Cards Types` field to store the content types of the cards
- Will currently need to be manually filled in but will be automated in the future (currently being worked on)

![](https://i.imgur.com/lMHUcTl.png =550x)

----

### Contentful

**Update to `Solution Article` content model**

- New `Reading Time` field to store the reading time of an article
- Removes the need to fetch the body of the article to calculate the reading time for each card
- Will currently need to be manually filled in but will be automated in the future

----

### SDK

- `contentful.editorialPage.read`
    - Reads editorial page entry from Contentful
    - Reads only one level of nesting (compared to 4 before); it only reads the link to each card rather than the whole entry
- `contentful.carouselCards.read`
    - Reads carousel card entry from Contentful
    - Selects only the fields required to render card
- `buildCarouselCard`
    - Modifies carousel card data into format as required by the card to remove the need to parse data in the card component
    - Fetches user data from People API only for question and article cards

----

### Styleguide

- New `Carousels`,  `Carousel` and `CarouselCard` components
- `ContentCardsSliders` and `ContentCard` components have not been changed so it is backwards compatible with existing sliders and content cards for learning hubs and partnerships pages


----

### Styleguide

- `Carousels`
  - Handles loading multiple carousels with grey dividers in between and loading placeholder when fetching carousels from Contentful
- `Carousel`
  - Similar to existing `ContentCardsSlider` component without expensive dependencies and simplified window resize logic
  - Only the visible cards will be rendered on first load. Cards on other slides are only loaded when the user goes to the slide 
- `CarouselCard`
  - Similar to existing `ContentCard` component
  - Fetches the data for each card based on the Contentful link so each card can load independently, fetching only the required fields
  - Shows a loading placeholder when fetching card data to prevent Cumulative Layout Shift

----

### Example

Fetch editorial page from Contentful

```javascript=
import { editorialPages } from '@apolitical/sdk';

useEffect(() => {
  editorialPages
    .read('home') // slug of the editorial page entry
    .then((page) =>
      setPageStates({...pageStates, carousels: (page && page.carousels) || [], isLoading: false })),
    .catch(() => setPageStates({ ...pageStates, isLoading: false, error: true }));
}, []);
```

----

### Example

Pass carousels data, loading state and build card function to `Carousels` component

```javascript=
import { buildCarouselCard } from '@apolitical/sdk';
import { Carousels } from '@apolitical/styleguide2';

<Carousels 
  isLoading={isLoading}
  carousels={carousels}
  buildCardData={buildCarouselCard}
  gtmContext="Home"
/>
```

----

### Example

![](https://i.imgur.com/MEUkrPa.png =700x)

----

### Example

Merge requests

- [Apolitical SDK](https://gitlab.com/apolitical/node-modules/apolitical-sdk/-/merge_requests/39)
- [Apolitical Styleguide](https://gitlab.com/apolitical/node-modules/apolitical-styleguide/-/merge_requests/124)
- [Core Pages](https://gitlab.com/apolitical/frontends/core-pages/-/merge_requests/181)

----

After optimisations, the performance of the page has improved :tada: 

- Total Blocking Time: 5,090ms to 908ms (**~80%** improvement)
- Time to Interactive: 8.2s to 4.1s (**50%** improvement)
- Speed Index: 3.2s to 2.3s (**~30%** improvement)

![](https://i.imgur.com/sQLWV8Z.png =800x)

----

![](https://i.imgur.com/Q16OlWf.png =550x)

- Note: the Lighthouse reports generated in the pipeline can be different to ones run in the browser so the overall score may seem low

---

## Further work
:nerd_face:

----

### Carousels component
- Update pages already built for new navigation to use the new `Carousels` components
- Update learning hub and partnerships pages to use new `Carousels` components and remove slider code
- Revisit window resizing logic in Carousel component. It has been simplified and does not adapt to window resizing but can be restored to previous logic if necessary.

----

### Styleguide
- Deprecate styleguide slider component and Slider content model on Contentful when learning hubs and partnerships pages have been updated
- Add functionality from `CarouselCard` component to `ContentCard` so that only one component will be used for carousels and individual cards

----

### Contentful apps
- Calculate and populate `Reading Time` field in `Solution Article` content model
- Automatically populate `Cards Types` field in `Carousel` content model

----

The performance of the carousels can still be improved so it would be good to investigate further :slightly_smiling_face:
