skill · sumi · v0.6.1
Rendimiento — Core Web Vitals como requisitos
Rendimiento web con Core Web Vitals como criterios de aceptación: presupuestos, guías para LCP, INP y CLS, imágenes, fuentes, coste de JavaScript y de terceros, caché y entrega, estrategia de renderizado, y cómo medir (laboratorio y campo) con evidencia. Úsala al construir páginas o componentes, añadir dependencias, scripts, imágenes o fuentes, elegir la estrategia de renderizado, o cuando algo vaya lento. Base independiente del framework: cuando se aplique una skill de un paquete de stack (nuxt-data-ssr, react-performance, shopify-performance-a11y, wp-performance-audit), úsala para lo específico del stack.
- Referencia
- sumi
- skill
- performance
- source
- plugins/sumi/skills/performance/SKILL.md
Los presupuestos se fijan antes de construir (.sumi/config.json → performanceBudget) y se comprueban antes de entregar. Valores por defecto, medidos en p75 en un móvil de gama media:
| Métrica | Presupuesto |
|---|---|
| LCP | ≤ 2.5 s |
| INP | ≤ 200 ms |
| CLS | ≤ 0.1 |
| JS inicial (gzip) | ≤ 170 KB en sitios de contenido; justifica más en las apps |
| Tamaño total de transferencia | ≤ 1.5 MB para una página de contenido típica |
LCP — haz que el hero llegue rápido
- Identifica el elemento LCP (normalmente la imagen hero o el titular).
- Debe estar en el HTML inicial (no inyectado por JS), sin carga diferida, con
fetchpriority="high"; precárgalo solo si se descubre tarde (fondo CSS, dentro de un componente). - Sírvelo adaptable (
srcset/sizes), en AVIF/WebP, desde un CDN y dimensionado para el hueco real. - Reduce el TTFB: caché estática/ISR/en el edge donde el contenido lo permita; evita las cascadas bloqueantes en el servidor.
- Elimina lo que bloquea el renderizado: CSS crítico pequeño, CSS no crítico diferido; sin scripts de terceros bloqueantes en el
<head>.
INP — mantén las interacciones instantáneas
- Mantén pequeños los manejadores de eventos: actualiza primero la UI y difiere el trabajo no urgente (
scheduler.yield(),requestIdleCallback, transiciones en React). - Divide las tareas largas de más de 50 ms; evita las lecturas síncronas de composición después de escribir.
- Envía menos JS: renderiza en el servidor el contenido estático, hidrata solo las islas interactivas, divide el código por ruta y por interacción (carga el código del modal en la primera apertura).
- Vigila a los terceros (widgets de chat, herramientas de A/B, gestores de etiquetas): cárgalos tras una interacción o en reposo, mediante una fachada cuando sea posible.
- Listas grandes: virtualiza o pagina; evita volver a renderizar árboles completos con cada pulsación de tecla.
CLS — nada salta
- Dimensiones o
aspect-ratioen cada imagen, vídeo, iframe y hueco de anuncio o embed. - Reserva espacio para el contenido tardío (banners, barras de cookies, bloques de apps, widgets de reseñas) o muéstralo en superposiciones que no empujen el contenido.
- Fuentes:
font-display: swapcon alternativas de métricas equivalentes (size-adjust,ascent-override) uoptionalpara el texto del cuerpo. - Anima solo
transform/opacity; nunca animes propiedades de composición.
Fuentes
- Máximo 2 familias, con subconjunto, WOFF2, alojadas por ti (o con el optimizador de fuentes del framework), y precarga solo los 1–2 archivos usados sobre el pliegue. Fuentes variables cuando reemplacen ≥ 3 archivos estáticos.
Imágenes y medios
- Formato y tamaño correctos por hueco;
loading="lazy"bajo el pliegue;decoding="async". - Usa el pipeline de imágenes de la plataforma (Nuxt Image, next/image,
image_urlde Shopify con anchos,wp_get_attachment_imagede WordPress con sizes). - Vídeo: sin vídeos hero con reproducción automática en móvil salvo que sean diminutos y sin sonido, con póster; carga diferida de los embeds tras una fachada.
Entrega y caché
- Caché inmutable de larga duración para los recursos con hash; caché corta o revalidada para el HTML.
- HTTP/2+ con compresión (Brotli). Preconecta solo con los orígenes necesarios en los primeros segundos (máximo 2–3).
- Elige el renderizado por ruta: estático/ISR para contenido, SSR para lo personalizado, CSR solo tras autenticación para pantallas de tipo aplicación.
Dependencias
Comprueba el coste antes de añadir (bundlephobia / pkg-size, o el analizador de bundles). Prefiere las APIs nativas y las bibliotecas pequeñas y enfocadas. Elimina los polyfills sin usar para objetivos evergreen.
Medición (evidencia obligatoria)
- Laboratorio: Lighthouse (móvil, con limitación) o Unlighthouse para sitios de varias páginas; WebPageTest para las cascadas. Las ejecuciones de navegación no pueden medir el INP: usa el TBT como su indicador sustituto, o una ejecución timespan de Lighthouse sobre la interacción. Registra las cifras de antes y después en el expediente de funcionalidad.
- Campo: CrUX / Search Console / la biblioteca
web-vitalsinformando a analítica para datos reales de p75. Pasar en laboratorio no garantiza pasar en campo. - Bundles: el analizador del framework (
nuxi analyze,@next/bundle-analyzer,vite-bundle-visualizer). - Interacciones: el panel Performance de Chrome DevTools con limitación de CPU 4× para depurar el INP.
Señales de relleno genérico
- Carga diferida de la imagen hero;
loading="lazy"en todo. - Importar una biblioteca entera para una sola función (
lodash,moment, paquetes de iconos sin tree-shaking). - Obtención de contenido en el cliente que podría renderizarse en el servidor;
'use client'/ envoltorios solo de cliente en lo alto del árbol. - Animaciones sobre
top/left/width/height; listeners de scroll sin passive ni throttling. - Scripts de terceros sin límite en el head.
Lista de verificación
- Elemento LCP identificado y priorizado; imágenes dimensionadas, formatos modernos, dimensiones fijadas.
- Sin recursos nuevos que bloqueen el renderizado; terceros nuevos diferidos o justificados.
- El JS añadido para la funcionalidad, medido; presupuesto respetado o excepción justificada.
- Cifras de Lighthouse móvil de antes y después registradas como evidencia.