Browser & Frontend Runtime
Core Web Vitals: fix a failing article page
Reading about LCP phases and the hydration INP trap is not the same as pulling a real page out of the red. Build a media-style article page that fails all three vitals, instrument it with field RUM, then fix each by its dominant phase and part — proving every step with measurements.
Turn the unit’s mental model into a reproducible loop: wire web-vitals RUM with attribution, read the dominant phase/part for each metric, apply the targeted fix, defend the wins with a throttled CI gate, and verify with before/after numbers under realistic throttling.
Take a server-rendered article page that fails LCP, INP, and CLS (your own or the starter described below) and bring all three under the good thresholds at simulated p75 — LCP ≤2.5 s, INP ≤200 ms, CLS ≤0.1 — proving each step with attributed measurements, not estimates.
- A before/after table for all three metrics: LCP (with its four-phase split), INP (with its three-part split), CLS (with the worst session-window contributors) — measured under identical throttling, not estimated.
- Each fix is justified by the attribution: you name the dominant phase/part it targeted and show that phase/part shrinking in the re-measured RUM log (not assumed).
- All three metrics land under the good thresholds at simulated p75 — LCP ≤2.5 s, INP ≤200 ms, CLS ≤0.1 — and the CI gate passes on the fixed build and fails if you reintroduce any regression.
- A one-paragraph write-up explaining one tradeoff you hit where a fix for one vital threatened another (e.g. ad space reservation vs the LCP candidate, or inlined CSS vs TTFB) and how you measured the net effect across all three.
- Add soft-navigation instrumentation: if the comments or related-articles flow does a client-side route change, capture LCP/INP for the soft navigation with PerformanceObserver soft-navigation entries or RUM marks, and show the route-change vitals next to the initial-load numbers.
- Build a RUM dashboard that segments p75 by device class and country, and show a device-class regression that a single lab run would miss.
- Wire LoAF into the INP attribution so a slow interaction names the exact script (file:line) that dominated the slow frame, then fix that script and re-measure.
- Add a synthetic-vs-field reconciliation: collect both your lab numbers and a CrUX (or simulated field) p75, explain the gap, and adjust your CI throttling profile until the lab predicts the field within a tolerance you document.
This is the loop you run on every real vitals incident: instrument with field RUM and attribution first, read the dominant phase (LCP) and part (INP) and the worst session window (CLS), fix each by what the attribution names — not the convenient fix — defend the wins with a throttled CI gate, and verify with before/after numbers under identical throttling. Because the three share a budget, you measure all of them around every change. Doing it once on a toy article page makes the production version muscle memory.