<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

----
### 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)

----
### 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

----
### 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)

----

- 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:
{"metaMigratedAt":"2023-06-17T19:47:54.414Z","metaMigratedFrom":"YAML","title":"Carousel Optimisations","breaks":true,"description":"View the slide with \"Slide Mode\".","slideOptions":"{\"theme\":\"solarized\",\"transition\":\"slide\"}","contributors":"[{\"id\":\"187fb0fa-fcd9-4872-8dc1-db5638287374\",\"add\":9795,\"del\":2998}]"}