---
description: Use when working on page speed, bundle size, slow rendering, or Core Web Vitals.
alwaysApply: false
---

# Web performance

## Measure first
- Get a baseline before changing anything: Lighthouse (`npx lighthouse <url> --only-categories=performance`), the browser Performance panel, or field data (CrUX/RUM). Report before/after numbers.
- Targets: LCP < 2.5s, INP < 200ms, CLS < 0.1 on a mid-range mobile profile.

## LCP
- Find the LCP element. Serve it as an optimized image (AVIF/WebP, correct `sizes`/`srcset`) with `fetchpriority="high"`; never lazy-load it.
- Avoid render-blocking scripts and CSS; preload critical fonts, use `font-display: swap`.
- Server-render or statically generate above-the-fold content.

## INP
- Break up long tasks (> 50ms): defer non-urgent work (`scheduler.yield()` or `setTimeout`), debounce input handlers, move heavy work to a Web Worker.
- Avoid re-rendering large trees on each keystroke (virtualize long lists).

## CLS
- Set `width`/`height` or `aspect-ratio` on images, video, ads and embeds. Reserve space for late content; don't insert banners above existing content.

## Bundle
- Check size with the bundler analyzer. Code-split routes and heavy components (`import()`), and replace heavy dependencies (e.g. moment -> `Intl`/date-fns).
- Third-party scripts load `async`/`defer` or after interaction.

## Don't
Don't micro-optimize without a measured problem, or trade correctness for speed.
