4.7 KiB
| name | description |
|---|---|
| web-vitals-performance | Optimize real-world web performance according to Google Core Web Vitals (INP <= 200ms, LCP <= 2.5s, CLS <= 0.1). Enforces main thread budgets, scheduler.yield() task chunking, AVIF media pipelines, font metric overrides, and third-party script isolation. |
Web Vitals & Real-World Performance Engineering
Ce skill garantit que les interfaces atteignent les seuils d'excellence des Core Web Vitals officiels (LCP ≤ 2.5s, INP ≤ 200ms, CLS ≤ 0.1) mesurés sur le terrain (Google Chrome User Experience Report - CrUX).
🎯 Déclencheurs d'Activation
Activez ce skill dès que :
- Vous chargez des médias lourds (images d'en-tête, bannières, galeries, vidéos).
- Vous intégrez des polices typographiques web (Google Fonts, polices locales).
- Vous développez des interactions utilisateur riches susceptibles de bloquer le thread principal (recherche instantanée, filtrage de tableau de données, calculs lourds côté client).
- Vous auditez ou optimisez les scores de performance d'une application avant son déploiement.
⚡ 1. Optimisation de l'INP (Interaction to Next Paint ≤ 200ms)
L'INP a définitivement remplacé le FID. Il mesure le délai entre une action utilisateur (clic, frappe, tap) et le moment exact où le navigateur affiche la prochaine image.
Règle d'Or : Budget du Thread Principal < 50ms
Toute tâche JS dépassant 50ms est une « Long Task » qui dégrade l'INP.
Découpage des Tâches Longues avec scheduler.yield()
// Utilitaire moderne pour rendre la main au navigateur pendant un traitement lourd
async function yieldToMain() {
if ('scheduler' in window && 'yield' in (window as any).scheduler) {
await (window as any).scheduler.yield();
} else {
// Fallback standard
await new Promise((resolve) => setTimeout(resolve, 0));
}
}
export async function processLargeDataset(items: Array<any>) {
for (let i = 0; i < items.length; i++) {
// Traitement de l'élément
computeHeavyItem(items[i]);
// Toutes les 50 itérations, on cède le contrôle au thread principal pour afficher les clics/peintures
if (i % 50 === 0) {
await yieldToMain();
}
}
}
🚀 2. Optimisation du LCP (Largest Contentful Paint ≤ 2.5s)
L'élément LCP (souvent l'image du Hero ou le titre H1 principal) doit être peint immédiatement :
fetchpriority="high"Obligatoire sur l'image LCP :<img src="/images/hero.avif" alt="Tableau de bord de design" fetchpriority="high" loading="eager" decoding="async" width="1280" height="720" />- Préchargement des Polices Critiques :
<link rel="preload" href="/fonts/geist-sans.woff2" as="font" type="font/woff2" crossorigin="anonymous" /> - Format AVIF Prioritaire : Toujours servir l'AVIF en premier (gain de 20 à 35% de bande passante par rapport au WebP).
📐 3. Élimination Totale du CLS (Cumulative Layout Shift ≤ 0.1)
Le décalage de mise en page survient lorsque des éléments changent de position pendant le chargement.
Solutions Anti-CLS :
- Ratio d'aspect explicite : Tout conteneur d'image ou vidéo doit avoir une propriété CSS
aspect-ratioou des attributswidthetheight. - Espace réservé pour la typographie : Utilisez
@font-faceavec des métriques de substitution pour éviter le saut entre police système et police web :@font-face { font-family: 'Geist-Fallback'; src: local('Arial'); ascent-override: 92%; descent-override: 24%; size-adjust: 102%; } - Squelettes de chargement (Skeletons) : Réservez précisément la hauteur des blocs de contenu asynchrones.
📦 4. Gestion des Scripts Tiers (Analytics & Trackers)
Ne jamais insérer de balise <script src="..."> synchrone dans le <head> pour un outil d'analyse :
- Utilisez
strategy="lazyOnload"oustrategy="worker"(via Partytown pour déporter l'exécution dans un Web Worker). - Isolez les iframes et widgets d'assistance avec l'attribut
loading="lazy".
📋 Checklist de Conformité Web Vitals
- L'image principale LCP possède
fetchpriority="high"etloading="eager". - Aucun média ne manque de dimensions ou d'attribut CSS
aspect-ratio. - Les polices web utilisent
font-display: swapet sont préchargées en WOFF2 local. - Les écouteurs d'événements lourds (
scroll,input,resize) sont découpés viascheduler.yield()ou temporisés (debounced). - Le score CLS en navigation simulée est inférieur à 0.05.
- Les images sont servies au format AVIF avec fallback WebP.