<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:
{"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}]"}
    269 views