Skip to content

DOC

Optimiser Core Web Vitals avec Perf Auditor

Audit exhaustif de performance frontend et backend, optimisations priorisées

Optimiser Core Web Vitals avec Perf Auditor

Contexte

Votre site est lent et vous devez optimiser Core Web Vitals (LCP, INP, CLS) avant release. perf-auditor analyse le bundle, les requêtes réseau, le lazy loading, la mémoire, et génère un plan d’optimisation priorisé avec impact estimé.

Prérequis

  • Build production créé : npm run build
  • Serveur local en écoute pour tests (Next.js, Nuxt, etc.)
  • Fichiers de build accessibles : .next/, dist/, .nuxt/, etc.
  • Outils optionnels : Lighthouse CLI, PageSpeed Insights API key
  • Accès à docs/todo.md pour créer les tâches

Étapes

1. Invoquer perf-auditor

/ulk:perf-auditor
# ou
perf-auditor

2. Phase 1 : Reconnaissance

L’agent détecte :

🔍 Perf Auditor — Initialisation
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Framework       : Next.js 15 (App Router)
Bundler         : Turbopack
Build size      : 245 KB (budget: 200 KB → OVER)
Build time      : 18.3s (budget: 15s → OVER)

Backend         : Node.js 20 + Express
DB              : Neon PostgreSQL
Caching         : Redis (détecté)

Métriques actuelles:
  LCP (target: 2.5s)  : N/A (lighthouse nécessaire)
  INP (target: 200ms) : N/A
  CLS (target: 0.1)   : N/A

3. Phase 2 : Audit Frontend

Bundle Size Analysis :

npx next/bundle-analyzer
du -sh .next/static/

Détecte les dépendances lourdes :

PackageTailleAlternativeGain
moment290 KBdayjs-280 KB
lodash70 KBnative (tree-shake)-70 KB
chart.js200 KBlightweight-charts-150 KB

Lazy Loading :

grep -r "import " src/ --include="*.tsx" | grep -v "^import.*from.*'" | head -20
# Identifie les imports statiques qui devraient être dynamic()

Output :

🔴 [CRITICAL] HeavyChart.tsx imported statically
  → Solution: dynamic(() => import('./HeavyChart'), { ssr: false })
  → Estimated savings: 180 KB de bundle initial

🟡 [WARNING] Three.js imported au root
  → Solution: Lazy load seulement si utilisateur hover le canvas
  → Estimated savings: 600 KB si utilisateur évite la section

Images :

find src -name "*.png" -o -name "*.jpg" | du -c
# Vérifier la compression, les formats modernes (WebP)

4. Phase 3-4 : Audit Backend + Requêtes

API Response Time :

curl -w "@curl-format.txt" -o /dev/null -s https://api.example.com/endpoints
# Teste TTFB (Time to First Byte)

N+1 Queries :

# Si Prisma disponible
npx prisma debug
# Détecte queries redondantes

Database Indexes :

SELECT schemaname, tablename, indexname FROM pg_indexes
WHERE tablename NOT LIKE 'pg_%'
ORDER BY tablename;

Cache Strategy :

  • Redis présent ? Vérifier TTL et hit rate
  • HTTP cache headers ? Content-Encoding ?
  • CDN active ? (Vercel, Cloudflare)

5. Phase 5-6 : Consolidation et Score

Matrice de complétude :

╔════════════════════════════════════════════════════════════╗
║ AUDIT PERFORMANCE — Résumé                                ║
╠════════════════════════════════════════════════════════════╣
║                                                            ║
║ Bundle Size             : 5/10  (245 KB vs 200 KB budget) ║
║ Core Web Vitals         : 6/10  (LCP 3.2s vs 2.5s target) ║
║ TTFB                    : 7/10  (340ms vs 300ms target)   ║
║ Memory & Jank           : 8/10  (No major leaks detected) ║
║ Caching Strategy        : 9/10  (Redis + HTTP cache OK)   ║
║                                                            ║
║ Score global            : 7/10  (Passable, optimisable)  ║
║                                                            ║
╠════════════════════════════════════════════════════════════╣
║ Effort estimé           : 3-4 hours pour +2 points       ║
║ ROI                     : +20% page load time, -45 KB     ║
╚════════════════════════════════════════════════════════════╝

7. Rapport et tâches

Rapport détaillé : docs/reports/audit-perf-20260414.md

## Optimisations priorisées (High Impact → Low Effort)

### 1. 🔴 CRITICAL : Lazy load Heavy Chart (+180 KB savings)
- Fichier: `src/pages/dashboard.tsx:24`
- Current: `import HeavyChart from './HeavyChart'`
- Fix: `const HeavyChart = dynamic(() => import('./HeavyChart'), { ssr: false })`
- Impact: -180 KB bundle initial
- Effort: 5 min
- Expected LCP: 3.2s → 2.8s

### 2. 🟡 HIGH : Replace moment with dayjs (-280 KB)
- Current dependency: moment (290 KB)
- Fix: npm uninstall moment && npm install dayjs
- Impact: -280 KB bundle
- Effort: 15 min (find & replace imports)
- Expected bundle: 245 KB → 65 KB (!)

### 3. 🟡 HIGH : Enable Gzip compression on Vercel
- Current: Not configured
- Fix: Next.js handles automatically, verify vercel.json
- Impact: -40% on network transfer
- Effort: 2 min
- Expected TTFB: 340ms → 280ms

### 4. 🟢 MEDIUM : Add NextImage optimization
- Current: Using native <img> tags
- Fix: Replace with `next/image` for auto-optimization
- Impact: -60% image size via WebP
- Effort: 30 min
- Expected LCP: 2.8s → 2.3s ✅

### 5. 🟢 MEDIUM : Implement Image Lazy Loading (native)
- Current: All images load above-the-fold
- Fix: Add loading="lazy" to below-fold images
- Impact: -100 KB on initial request
- Effort: 20 min
- Expected LCP: 2.3s → 2.1s ✅

Tâches créées :

- [ ] Perf: Lazy load HeavyChart component (+180 KB savings)
- [ ] Perf: Replace moment with dayjs (-280 KB)
- [ ] Perf: Verify Gzip compression on Vercel
- [ ] Perf: Replace <img> with next/image
- [ ] Perf: Add loading="lazy" to below-fold images

Exemple de sortie

═══════════════════════════════════════════════════════════
Perf Audit Summary — portfolio-saas
═══════════════════════════════════════════════════════════

BUNDLE SIZE
  Current  : 245 KB
  Budget   : 200 KB
  Status   : ❌ OVER by 45 KB

  Top packages:
    chart.js      : 200 KB (UNUSED in current routes)
    moment        : 290 KB (can use dayjs: 2 KB)
    lodash        : 70 KB (partial usage, tree-shake)

CORE WEB VITALS (Simulated)
  LCP  : 3.2s (target: 2.5s) ❌ OVER
  INP  : 145ms (target: 200ms) ✅ OK
  CLS  : 0.08 (target: 0.1) ✅ OK

TTFB
  Current : 340ms
  Target  : 300ms
  Issue   : Missing Gzip compression

RECOMMENDATIONS
  Priority 1 (Do first)
    → Lazy load chart.js (-200 KB) [5 min]
    → Replace moment with dayjs (-290 KB) [15 min]
  Priority 2 (Do second)
    → Use next/image (-60% image size) [30 min]
    → Enable lazy loading on images [20 min]
  Priority 3 (Nice to have)
    → Implement CSS code splitting [1h]
    → Add service worker for offline [2h]

ESTIMATED RESULTS
  After all fixes:
    Bundle: 245 KB → 95 KB (-61%)
    LCP: 3.2s → 2.1s ✅
    TTFB: 340ms → 250ms ✅
    Time investment: 1.5 hours

Variantes

  • Variante A : Focus critiques uniquement--critical-only pour ignorer les recommandations “nice-to-have”
  • Variante B : Lighthouse detailed report — Si PageSpeed Insights API disponible, compare avec métriques réelles de Google
  • Variante C : Comparaison pré/post — Si audit antérieur existe, reporte l’évolution des scores

Agents enchaînés

Flux linéaire (peut être parallélisé avec audits a11y et code) :

perf-auditor (07)
  ├─ Phase 1 : Reconnaissance (5 min)
  ├─ Phase 2 : Audit frontend (20 min)
  ├─ Phase 3 : Audit backend (15 min)
  ├─ Phase 4 : Analyse requêtes (10 min)
  └─ Phase 6-7 : Rapport + optimisations (10 min)

Si lancé via Black Emperor mode=release, parallélisé avec a11y-auditor et code-auditor.

Troubleshooting

SymptômeCause probableRésolution
”Build size unknown”Build n’existe pasLancez npm run build d’abord
Lighthouse metrics N/APageSpeed API key manquantOptionnel : ajouter via env var ou ignorer (estimates basées sur analyse statique)
Database N+1 queries non détectésPrisma logging pas activéAjouter log: ['query'] dans Prisma schema ou utiliser npx prisma debug
Images non détectéesImages servies depuis CDN externeAudit liste les domaines externes détectés

Voir aussi

  • ./02-blackemperor-pre-release.md — Audit pré-release (inclut perf)
  • ./06-perf-auditor.md — Cette fiche (performance Core Web Vitals)
  • ./05-a11y-audit.md — Audit accessibilité (parallélisable)
  • agents/audit/07-perf-auditor.md — Documentation complète
  • agents/_shared/auditor-base.md — Base commune aux auditors
  • agents/_shared/checklists/performance-checklist.md — Checklist Core Web Vitals