Background
ReadingLists has started as a small extension with different authors and changed several times scope and directions.
Not only has this lead to accumulated technical debt and outdated approaches, it also hasn't seen an evaluation of performance for large-scale rollout – only with some important recent exceptions like T405393 or rollout of BloomFilters.
This EPIC is result of T409354.
As of current the perceived performance of loading the ReadingLists feature is sluggish due to numerous reasons,
largest contentful paint (LCP) on beta is 3.0 seconds, so over the general guidance of 2.5s. On testwiki (on my 1 list with 0 items) 3.9s.
Several technical reasons contribute to this long loading time*:
- Dead DB query on every page view
- Loading of Vue.js library to show anything below title.
- CSS-only progress bar. Loading bar could be shown before Vue has loaded. Depending on CodexPHP usage above.
- Collections list item (Card) thumbnails are delaying largest contentful paint as they are implemented as CSS background-images
- Unthrottled scroll handler. Infinite scroll reads the layout on every single scroll event.
- Doubled lookup query for list-membership on a saved page
- Project ID not memoized
- Legacy title matching against multiple variants. Lookup matches up to 5 title variants.
- Serial API calls on mount
- Unused Codex components bundled. Two Codex components are shipped but nowhere used.
(* boldened are highest impact ones.)
Loading the list view from cache:
Loading the list view cold:
Possible impacts on users
First impression
- Sluggish experience: Users perceive a website as slow or unresponsive when the main content takes longer than 3 seconds to load.
- Loss of trust: Visitors may assume the site is poorly optimized or unreliable, especially on mobile devices or slower connections.
- Reduced satisfaction: Studies show that users begin to lose patience after 2–3 seconds of waiting, which can create frustration.
Engagement impacts
- Higher bounce rates: Google data indicates that as page load time increases from 1s to 3s, the probability of bounce increases by ~32%. Beyond 3s, that risk grows sharply.
- Lower engagement: Slow LCP reduces the likelihood of scrolling, interacting, or exploring additional content.
- Interrupted task flow: Users who come to complete a specific action (like reading an article or making a purchase) are more likely to abandon it.
What and how to measure
How we best measure these, before and after? For every item two numbers together: one deterministic value that proves the mechanism (query count, bytes, module size), and one latency percentile (p50/p75 over many runs) for the actual user effect. Always compare a "before" and an "after" on the same wiki with the same data, otherwise the numbers are not really comparable.
| What to measure | Applies to | How |
|---|---|---|
| DB query count (deterministic) | Dead page-view query; Doubled membership lookup; Project ID not memoized; Legacy title-variant matching | maintenance/benchmarkHotPaths.php resp. HotPathQueryCountTest (both in this coming patch) give the exact counts plus timing. For a full request we can anyway look at the flame graph in XHGui via the WikimediaDebug header. |
| Main-thread / layout jank | Unthrottled scroll handler | DevTools Performance panel: record one scroll session and compare the forced-reflow (layout-thrashing) warnings and the long-task count resp. duration. |
| Time-to-first-entry | Serial API calls on mount | Network waterfall plus a performance.mark/measure; after the fix the two requests should overlap. |
| Module bundle size | Unused Codex components | load.php?modules=ext.readingLists.special&only=scripts (and only=styles) response Content-Length, before against after removing the components. This is deterministic. |
| Real users | Scroll handler; Thumbnails; Serial API (the frontend items, once deployed) | NavigationTiming RUM in Grafana (firstPaint/LCP/loadEventEnd percentiles), compared over the existing experiment cohorts. |
Prior work
Goal
Improve/speed up (perceived) loading time/rendering time of ReadingLists.
Acceptance criteria for done
- All sub-tasks are resolve (or declined)
High impact improvement
- Dead DB query on every page view https://gerrit.wikimedia.org/r/c/1319549
- T434586: ReadingLists to use Codex PHP `CdxCard` for server-side item rendering (stalled for further exploration in regards to CustomLists and expanding other RL functionality ) Loading of Vue.js library blocks showing anything below title.
- T434624: Thumbnail: Allow image to render as an `<img>` element instead of a CSS background image Collections list item (Card) thumbnails are delaying largest contentful paint as they are implemented as CSS background-images
- T434582: Unthrottled scroll handler Infinite scroll reads the layout on every single scroll event.
Medium impact improvement
- T434588: Doubled list-membership lookup on a saved page
- T434590: Project ID not memoized
- T434600: Legacy title matching against multiple variants. Lookup matches up to 5 title variants.
- T434602: Serial API calls on mount
- T433648: CodexModule: detect and warn on declared-but-unused entries in 'codexComponents' Two Codex components are bundled/shipped but nowhere used.
- T434603: CSS-only progress bar instead of the Vue one Loading bar could be shown before Vue has loaded. If useful is depending on CodexPHP usage above. VE: CSS progress bar and with it faster system feedback to users is done, task remaining for rendering flow considerations
- T434613: Skeleton loader (Codex component)
