496303471d
---ci--- project: atelier phase: 7 milestone: v0.1 status: complete phase_role: final milestone_complete: true requirements: covered: [ATELIER-01, ATELIER-02, ATELIER-03, ATELIER-04, ATELIER-05, ATELIER-06, ATELIER-07, ATELIER-08, ATELIER-09, ATELIER-10, ATELIER-11, ATELIER-12, ATELIER-13, ATELIER-14, ATELIER-15, ATELIER-16, ATELIER-17, ATELIER-18, ATELIER-19, ATELIER-20, ATELIER-21, ATELIER-22, ATELIER-23, ATELIER-24, ATELIER-25, ATELIER-26, ATELIER-27, ATELIER-28, ATELIER-29, ATELIER-30, ATELIER-31, ATELIER-32, ATELIER-33, ATELIER-34, ATELIER-35] partial: [] ship: milestone: v0.1 type: NFR tag: v0.0.7 merge: milestone/v0.1-atelier -> main release: https://git.cloudinit.dev/cloudinit-bot/atelier/releases/tag/v0.0.7 ---/ci--- Milestone v0.1 — Initial Framework (NFR, complete). 8 core principles (C1-C8), 11 domains, 110 domain principles, 27 derived docs, 4 good + 3 bad examples, 4 language docs, full matrix, 3 review docs. All 35 requirements covered. 7 patches (v0.0.0 pre-execution through v0.0.7 final). v0.0.7 IS the v0.1.0 milestone release.
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 | |