โก Core Web Vitals โ What Interviewers Want to Hear
Core Web Vitals (CWV)
LCP โ Largest Contentful Paint
Target: < 2.5s
Biggest visible image/text loaded
Fix: Preload hero image, optimize server response, remove render-blocking resources
CLS โ Cumulative Layout Shift
Target: < 0.1
Unexpected layout shifts
Fix: Always set width/height on images, avoid inserting content above existing, use transform for animations
INP โ Interaction to Next Paint
Target: < 200ms
Response latency of interactions
Fix: Break up long tasks, use Web Workers for heavy compute, avoid main thread blocking
Critical Rendering Path
HTML parsing Browser builds DOM tree
CSS parsing Browser builds CSSOM tree
Render tree DOM + CSSOM combined (excludes display:none)
Layout Calculate position/size of elements
Paint Fill in pixels
Composite Layer compositing (GPU)
โ JS blocks HTML parsing! Use defer/async. CSS blocks rendering too!
What Triggers Layout (Reflow) ๐ธ
- โ Changing width, height, padding, margin, border
- โ Reading offsetWidth, offsetHeight, getBoundingClientRect (force sync layout)
- โ Adding/removing DOM elements
- โ Changing font-size
โ Prefer transform/opacity (GPU composited, no reflow)
// Bad โ layout thrashing el.style.left = el.offsetLeft + 1 + "px"; // read then write in loop // Good โ batch reads then writes const positions = els.map(e => e.offsetLeft); // all reads els.forEach((e,i) => e.style.left = positions[i] + 1 + "px"); // all writes
Code Splitting Strategy
- โ Route-based splitting (default in Next.js) โ biggest win
- โ Component-based: lazy load heavy components (charts, editors, modals)
- โ Vendor splitting: separate vendor bundle (changes less often, better caching)
- โ Dynamic imports: import('./module') for on-demand code
๐ผ๏ธ Asset Optimization
Image Optimization
Format AVIF > WebP > JPEG/PNG. Use <picture> for fallbacks.
Sizing Serve correct size with srcset + sizes
Lazy load loading='lazy' for below-fold. Eager for LCP image.
Blur placeholder Show low-quality placeholder while loading (LQIP)
CSS sprites Combine small icons into one image (now replaced by SVG sprites)
Font Optimization
/* Preconnect to font host */
<link rel="preconnect" href="https://fonts.googleapis.com" />
/* Preload critical font */
<link rel="preload" as="font" type="font/woff2"
href="/fonts/inter.woff2" crossorigin />
/* Avoid FOUT/FOIT */
@font-face {
font-family: "Inter";
font-display: swap; /* show fallback, swap when ready */
src: url("inter.woff2") format("woff2");
} Bundle Optimization
- โ Tree shaking โ import named exports, not default objects (lodash-es not lodash)
- โ Analyze bundle: webpack-bundle-analyzer, source-map-explorer
- โ Avoid moment.js (500kb) โ use date-fns or dayjs
- โ Compress: Gzip or Brotli (Brotli is ~20% smaller)
- โ Minification: JS (Terser), CSS (cssnano), HTML
Caching Strategy
Content hash in filename main.a3f9b2.js โ safe to cache forever
Service Worker Cache-first for shell, network-first for data
HTTP cache Cache-Control: max-age=31536000, immutable for hashed assets
React Query / SWR Client-side data caching, background revalidation, stale-while-revalidate
Memoization useMemo, React.memo, server-side lru-cache