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.mdpour 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 :
| Package | Taille | Alternative | Gain |
|---|---|---|---|
| moment | 290 KB | dayjs | -280 KB |
| lodash | 70 KB | native (tree-shake) | -70 KB |
| chart.js | 200 KB | lightweight-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-onlypour 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ôme | Cause probable | Résolution |
|---|---|---|
| ”Build size unknown” | Build n’existe pas | Lancez npm run build d’abord |
| Lighthouse metrics N/A | PageSpeed API key manquant | Optionnel : ajouter via env var ou ignorer (estimates basées sur analyse statique) |
| Database N+1 queries non détectés | Prisma logging pas activé | Ajouter log: ['query'] dans Prisma schema ou utiliser npx prisma debug |
| Images non détectées | Images servies depuis CDN externe | Audit 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èteagents/_shared/auditor-base.md— Base commune aux auditorsagents/_shared/checklists/performance-checklist.md— Checklist Core Web Vitals