Lab
Performance Audit & Fix
25 min
Intermediate3 Free Attempts
Instructions
Objective
You are given a React application with severe performance problems. Your task is to identify and fix issues affecting all three Core Web Vitals: LCP, CLS, and INP.
The Problem Application
The application is a product listing page with the following deliberate performance issues:
LCP Issues
- Hero image is a 2MB unoptimized PNG with no width/height attributes
- Three render-blocking Google Fonts loaded via
<link>in the head - All CSS is in a single large bundle (no critical CSS extraction)
- No preloading of the hero image
CLS Issues
- Product images have no width/height or aspect-ratio set
- A promotional banner is dynamically injected after 2 seconds
- Web font swap causes visible layout shift (no
size-adjust) - An ad placeholder has no reserved height
INP Issues
- Product filtering runs a synchronous loop over 10,000 items on every keystroke
- Sort function blocks the main thread for 300ms+
- Click handlers trigger synchronous layout recalculations (forced reflow)
Your Tasks
Task 1: Fix LCP (35 points)
- Convert the hero image to use
<picture>with AVIF/WebP sources and a JPG fallback - Add
width,height, andfetchpriority="high"to the hero image - Add
<link rel="preload">for the hero image - Use
font-display: swapfor custom fonts and preload the primary font file - Extract critical above-the-fold CSS into an inline
<style>block
Task 2: Fix CLS (30 points)
- Add
widthandheightattributes (or CSSaspect-ratio) to all product images - Reserve space for the promotional banner using
min-heightbefore it loads - Add
size-adjust,ascent-override, anddescent-overrideto the@font-facerule to minimize font swap shift - Set a fixed
min-heighton the ad placeholder container
Task 3: Fix INP (35 points)
- Debounce the search/filter input with a 300ms delay
- Break the product filtering into chunks using
setTimeout(fn, 0)orscheduler.yield()to yield to the main thread - Move the sort comparison into a Web Worker or break it into yielding chunks
- Replace forced reflow patterns (reading
offsetHeightafter writing styles) withrequestAnimationFramebatching
Starter Code
The starter code below represents the broken application. Fix the issues in place.
Evaluation Criteria
Your submission will be evaluated on whether the fixes correctly address each Core Web Vital issue. You do not need to run Lighthouse — the grading rubric checks your code for the specific optimization patterns.
Grading Rubric
LCP Fix — Hero image uses <picture> with AVIF/WebP sources, has width/height and fetchpriority='high', a <link rel='preload'> is added, fonts use font-display: swap and primary font is preloaded, critical CSS is inlined35 points
CLS Fix — Product images have width/height or aspect-ratio, promo banner container has min-height to reserve space even before content loads, @font-face includes size-adjust/ascent-override/descent-override, ad placeholder has a fixed min-height30 points
INP Fix — Search input is debounced (300ms), product filtering uses chunked processing with setTimeout or scheduler.yield to avoid blocking, forced reflow is eliminated by using requestAnimationFrame for style reads/writes35 points
Your Solution
Use any programming language
3 free attempts remaining