55 lines
2.2 KiB
Markdown
55 lines
2.2 KiB
Markdown
# Frontend Performance — Derived Rules
|
||
|
||
> Derives from `domains/performance/first-principles.md` P1 (Measure First), P9 (Perceived Performance).
|
||
|
||
## Measure First (P1)
|
||
|
||
- Lighthouse, Core Web Vitals (LCP, FID/INP, CLS), RUM (Real User Monitoring).
|
||
- A performance claim without a measurement is an opinion.
|
||
- Measure the 75th percentile (P75), not the average. The average hides the long tail.
|
||
|
||
## The Three Core Web Vitals
|
||
|
||
| Vital | What | Target (P75) |
|
||
|-------|------|--------------|
|
||
| LCP (Largest Contentful Paint) | When the main content loads | ≤ 2.5s |
|
||
| INP (Interaction to Next Paint) | When input is responded to | ≤ 200ms |
|
||
| CLS (Cumulative Layout Shift) | Visual stability | ≤ 0.1 |
|
||
|
||
- LCP > 4s is poor. INP > 500ms is poor. CLS > 0.25 is poor.
|
||
- Measure on mobile, not just desktop. Mobile is the long tail.
|
||
|
||
## Perceived Performance (P9)
|
||
|
||
- A skeleton screen beats a spinner. A spinner beats nothing.
|
||
- Optimistic UI updates: the click responds immediately; the server confirms later.
|
||
- Prefetch the next page on hover (if cheap). Prefetch is a bet, not a certainty.
|
||
|
||
## Bundle Size (P4 Resource Bounds, core C8 Economy)
|
||
|
||
- Ship less JavaScript. Every KB is parsed, compiled, and executed on the client.
|
||
- Code-split routes. Lazy-load below-the-fold. Don't ship the admin bundle to the user bundle.
|
||
- A 500KB JS bundle is large. A 2MB JS bundle is a defect.
|
||
|
||
## Images (P4, P6 Lazy by Default)
|
||
|
||
- WebP/AVIF, not JPEG/PNG. Modern formats are 30–50% smaller.
|
||
- `loading="lazy"` on below-the-fold images. `width`/`height` to prevent CLS.
|
||
- `srcset` for responsive images. Ship the right size to the right device.
|
||
- Never ship a 4K image to a 360px screen.
|
||
|
||
## Rendering (P7 Async When Independent)
|
||
|
||
- Server-render the first paint (SSR/SSG). Hydrate after.
|
||
- Avoid hydration waterfalls: a 3-second hydration is a 3-second blank page with a "loaded" script.
|
||
- Defer non-critical hydration. Interactive above the fold first; below the fold later.
|
||
|
||
## What Violates Frontend Performance
|
||
|
||
| Violation | Principle |
|
||
|-----------|-----------|
|
||
| 3MB JS bundle | P4, C8 |
|
||
| LCP > 4s on mobile | P1 (measured) |
|
||
| Layout shift on image load | CLS |
|
||
| Synchronous hydration of a 50KB page | P7 |
|
||
| No image optimization | P4 | |