Communitygithub.com

Blaise1030/astro-marketing

Optimiza el rendimiento web para lograr tiempos de carga más rápidos y una mejor experiencia de usuario. Úsalo cuando te pidan 'acelerar mi sitio', 'optimizar rendimiento', 'reducir tiempo de carga', 'arreglar carga lenta', 'mejorar velocidad de página' o 'auditoría de rendimiento'.

¿Qué es astro-marketing?

Esta skill de agente de IA se especializa en la optimización del rendimiento web basada en evidencia, utilizando señales reales de usuario para priorizar y trazas del navegador para diagnosticar. Se enfoca en la velocidad de carga, la capacidad de respuesta en tiempo de ejecución y la entrega eficiente de recursos. La skill guía al agente a través de un flujo de trabajo de medición que establece una línea base de campo y laboratorio, prioriza las deficientes Core Web Vitals reales, identifica la causa raíz mediante trazas de rendimiento de DevTools, y aplica cambios solo en los activos o código relacionados con los cuellos de botella medidos. Soporta plataformas como Chrome DevTools MCP (usando `performance_start_trace` y `performance_analyze_insight`) y proporciona presupuestos de rendimiento iniciales, optimizaciones de la ruta de renderizado crítica, estrategias para imágenes, fuentes, almacenamiento en caché, rendimiento en tiempo de ejecución, scripts de terceros y mediciones. El enfoque es práctico y basado en datos, con un fuerte énfasis en la verificación posterior a los cambios mediante mediciones de laboratorio equivalentes.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Blaise1030/astro-marketing/tree/HEAD/.agents/skills/performance

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Vista previa

Del README del skill

astro-marketing preview
astro-marketing preview
astro-marketing preview
astro-marketing preview

Documentación

Optimización de rendimiento

Optimización del rendimiento basada en evidencia, utilizando señales reales de usuario para priorizar y trazas del navegador para diagnosticar. Se centra en la velocidad de carga, la capacidad de respuesta en tiempo de ejecución y la entrega de recursos.

Cómo funciona

  1. Si una página se puede ejecutar, lee el flujo de trabajo de medición y establece una línea base de campo y laboratorio antes de editar.
  2. Prioriza las deficientes Core Web Vitals reales. Utiliza una traza de rendimiento de DevTools y sus informaciónes enfocadas para encontrar la causa.
  3. Inspecciona y cambia solo el código o los activos relacionados con los cuellos de botella medidos.
  4. Vuelve a ejecutar mediciones de laboratorio equivalentes e informa los valores antes/después, las condiciones y la incertidumbre. La verificación de campo queda pendiente hasta que lleguen suficientes datos de nuevos usuarios.

Cuando no exista una página ejecutable, realiza una inspección estática, pero llama a los hallazgos hipótesis, no regresiones medidas. Incluye el comando o el flujo de trabajo del navegador que puede verificar cada hipótesis de alto impacto.

Prefiere una herramienta de navegador que registre una traza de rendimiento y exponga informaciónes enfocadas. Con Chrome DevTools MCP, usa performance_start_trace y performance_analyze_insight; no enrutes el rendimiento a través de lighthouse_audit, que cubre categorías de Lighthouse no relacionadas con el rendimiento.

Presupuesto de rendimiento inicial

Los presupuestos deben reflejar los dispositivos objetivo, las redes, los tipos de página y los recorridos del usuario del producto. Los valores a continuación son barreras de protección iniciales para una página típica de contenido o comercio, no criterios universales de aprobado/reprobado. Conserva un presupuesto de proyecto existente cuando ya esté definido.

RecursoPresupuestoJustificación
Peso total de la página< 1.5 MBLimita el tiempo de transferencia y el costo de datos en redes objetivo restringidas; calibra con páginas representativas
JavaScript (comprimido)< 300 KBProtege el costo de análisis y ejecución
CSS (comprimido)< 100 KBLimita el trabajo de bloqueo de renderizado
Imágenes (sobre el pliegue)< 500 KBProtege los recursos probables de LCP
Fuentes< 100 KBLimita la transferencia de fuentes críticas
Terceros< 200 KBLimita el código fuera del control del producto

Ruta de renderizado crítica

Respuesta del servidor

  • TTFB < 800ms. El Time to First Byte debe ser rápido. Usa CDN, almacenamiento en caché y backends eficientes.
  • Habilita la compresión. Gzip o Brotli para activos de texto. Se prefiere Brotli (15-20% más pequeño).
  • HTTP/2 o HTTP/3. La multiplexación reduce la sobrecarga de la conexión.
  • Almacenamiento en caché en el borde. Almacena en caché HTML en el borde de la CDN cuando sea posible.
  • Considera Early Hints (HTTP 103) para la latencia del documento medida. Si una traza muestra una generación lenta de HTML y subrecursos críticos estables, envía un 103 interino con cabeceras Link antes de la respuesta final normal de la misma solicitud. Usa HTTP/2 o posterior. Una CDN puede sintetizar el 103 a partir de cabeceras Link en un 200 anterior, o el controlador de origen/borde puede emitirlo directamente. Los clientes no compatibles continúan con la respuesta final, pero confirma la compatibilidad actual del navegador y la infraestructura. Limita las sugerencias a precargas o preconexiones críticas probadas: las sugerencias inexactas desperdician ancho de banda. Cloudflare informó una mejora del 20-30% en LCP en una prueba artificial con mucho contenido de imagen; trátalo como un caso de estudio del proveedor, no como un ahorro esperado, y mide tu resultado. Consulta el ejemplo de implementación de 103 en MDN y el estudio de Cloudflare.

Carga de recursos

Preconexión a orígenes requeridos:

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://cdn.example.com" crossorigin>

Precarga de recursos críticos:

Precarga solo aquellos recursos cuyo descubrimiento tardío sea visible en la traza. Cada precarga compite por el ancho de banda y una solicitud de alta prioridad innecesaria puede retrasar el LCP.

<!-- Imagen LCP -->
<link rel="preload" href="/hero.webp" as="image" fetchpriority="high">

<!-- Fuente crítica -->
<link rel="preload" href="/font.woff2" as="font" type="font/woff2" crossorigin>

Prerenderiza las navegaciones probables siguientes con la API de Reglas de Especulación:

<script type="speculationrules">
{
  "prerender": [{
    "where": { "href_matches": "/*" },
    "eagerness": "moderate"
  }]
}
</script>

moderate espera una señal de intención más fuerte que los modos eager. Mide la tasa de aciertos de predicción, los bytes transferidos y el costo del servidor; un prerrenderizado incorrecto es aproximadamente una navegación no utilizada. Consulta core-web-vitals → LCP para conocer las compensaciones y la compuerta prerenderingchange necesaria para la analítica.

Difiere el CSS no crítico:

<!-- CSS crítico en línea -->
<style>/* Estilos sobre el pliegue */</style>

<!-- CSS no crítico -->
<link rel="preload" href="/styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/styles.css"></noscript>

Optimización de JavaScript

Difiere scripts no esenciales:

<!-- Bloqueo del analizador (evitar) -->
<script src="/critical.js"></script>

<!-- Diferido (preferido) -->
<script defer src="/app.js"></script>

<!-- Asíncrono (para scripts independientes) -->
<script async src="/analytics.js"></script>

<!-- Módulo (diferido por defecto) -->
<script type="module" src="/app.mjs"></script>

Patrones de división de código:

// División basada en rutas
const Dashboard = lazy(() => import('./Dashboard'));

// División basada en componentes
const HeavyChart = lazy(() => import('./HeavyChart'));

// División basada en funciones
if (user.isPremium) {
  const PremiumFeatures = await import('./PremiumFeatures');
}

Mejores prácticas de tree shaking:

// ❌ Importa toda la biblioteca
import _ from 'lodash';
_.debounce(fn, 300);

// ✅ Importa solo lo necesario
import debounce from 'lodash/debounce';
debounce(fn, 300);

Optimización de imágenes

Selección de formato

FormatoCaso de usoSoporte del navegador
AVIFFotos, mejor compresión92%+
WebPFotos, buen fallback97%+
PNGGráficos con transparenciaUniversal
SVGIconos, logotipos, ilustracionesUniversal

Imágenes responsivas

<picture>
  <!-- AVIF para navegadores modernos -->
  <source 
    type="image/avif"
    srcset="hero-400.avif 400w,
            hero-800.avif 800w,
            hero-1200.avif 1200w"
    sizes="(max-width: 600px) 100vw, 50vw">
  
  <!-- WebP fallback -->
  <source 
    type="image/webp"
    srcset="hero-400.webp 400w,
            hero-800.webp 800w,
            hero-1200.webp 1200w"
    sizes="(max-width: 600px) 100vw, 50vw">
  
  <!-- JPEG fallback -->
  <img 
    src="hero-800.jpg"
    srcset="hero-400.jpg 400w,
            hero-800.jpg 800w,
            hero-1200.jpg 1200w"
    sizes="(max-width: 600px) 100vw, 50vw"
    width="1200" 
    height="600"
    alt="Imagen principal"
    loading="lazy"
    decoding="async">
</picture>

Prioridad de imagen LCP

<!-- Imagen LCP sobre el pliegue: carga eager, alta prioridad -->
<img 
  src="hero.webp" 
  fetchpriority="high"
  loading="eager"
  decoding="sync"
  alt="Hero">

<!-- Imágenes bajo el pliegue: carga lazy -->
<img 
  src="product.webp" 
  loading="lazy"
  decoding="async"
  alt="Producto">

Optimización de fuentes

Estrategia de carga

/* Pila de fuentes del sistema como fallback */
body {
  font-family: 'Custom Font', -apple-system, BlinkMacSystemFont, 
               'Segoe UI', Roboto, sans-serif;
}

/* Prevenir texto invisible */
@font-face {
  font-family: 'Custom Font';
  src: url('/fonts/custom.woff2') format('woff2');
  font-display: swap; /* o optional para no críticas */
  font-weight: 400;
  font-style: normal;
  unicode-range: U+0000-00FF; /* Subconjunto a Latín */
}

Precarga de fuentes críticas

<link rel="preload" href="/fonts/heading.woff2" as="font" type="font/woff2" crossorigin>

Fuentes variables

/* Un archivo en lugar de múltiples pesos */
@font-face {
  font-family: 'Inter';
  src: url('/fonts/Inter-Variable.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-display: swap;
}

Estrategia de almacenamiento en caché

Cabeceras Cache-Control

# HTML (caché corto o sin caché)
Cache-Control: no-cache, must-revalidate

# Activos estáticos con hash (inmutables)
Cache-Control: public, max-age=31536000, immutable

# Activos estáticos sin hash
Cache-Control: public, max-age=86400, stale-while-revalidate=604800

# Respuestas de API
Cache-Control: private, max-age=0, must-revalidate

Almacenamiento en caché de Service Worker

// Cache-first para activos estáticos
self.addEventListener('fetch', (event) => {
  if (event.request.destination === 'image' ||
      event.request.destination === 'style' ||
      event.request.destination === 'script') {
    event.respondWith(
      caches.match(event.request).then((cached) => {
        return cached || fetch(event.request).then((response) => {
          const clone = response.clone();
          caches.open('static-v1').then((cache) => cache.put(event.request, clone));
          return response;
        });
      })
    );
  }
});

Rendimiento en tiempo de ejecución

Evitar el layout thrashing

// ❌ Fuerza múltiples reflujos
elements.forEach(el => {
  const height = el.offsetHeight; // Lectura
  el.style.height = height + 10 + 'px'; // Escritura
});

// ✅ Agrupa lecturas, luego agrupa escrituras
const heights = elements.map(el => el.offsetHeight); // Todas las lecturas
elements.forEach((el, i) => {
  el.style.height = heights[i] + 10 + 'px'; // Todas las escrituras
});

Debounce de operaciones costosas

function debounce(fn, delay) {
  let timeout;
  return (...args) => {
    clearTimeout(timeout);
    timeout = setTimeout(() => fn(...args), delay);
  };
}

// Debounce de manejadores de scroll/resize
window.addEventListener('scroll', debounce(handleScroll, 100));

Usa requestAnimationFrame

// ❌ Puede causar tirones
setInterval(animate, 16);

// ✅ Sincronizado con la actualización de la pantalla
function animate() {
  // Lógica de animación
  requestAnimationFrame(animate);
}
requestAnimationFrame(animate);

Virtualiza listas largas

// Para listas > 100 elementos, renderiza solo los elementos visibles
// Usa bibliotecas como react-window, vue-virtual-scroller, o CSS nativo:
.virtual-list {
  content-visibility: auto;
  contain-intrinsic-size: 0 50px; /* Altura estimada del elemento */
}

Navegaciones suaves con View Transitions

La API de View Transitions permite al navegador hacer una transición entre dos estados del DOM con un fundido cruzado (o animación personalizada) usando una única instantánea compuesta por GPU, sin doble renderizado, sin layout thrash, y la instantánea no cuenta para CLS.

Mismo documento (estilo SPA) — Baseline 2026:

// Envuelve la mutación del DOM que intercambia la vista
function navigate(newView) {
  if (!document.startViewTransition) return swapDOM(newView);
  document.startViewTransition(() => swapDOM(newView));
}

Documento cruzado (estilo MPA) — Chromium estable, mejora progresiva en otros:

/* En ambas páginas, origen y destino */
@view-transition { navigation: auto; }

Esa es toda la integración: las navegaciones del mismo origen ahora se desvanecen automáticamente. Para optar por elementos específicos en transiciones de elementos compartidos (por ejemplo, una miniatura que se expande a una imagen principal), asígnales un view-transition-name coincidente:

.product-thumb[data-id="42"], .product-hero { view-transition-name: product-42; }

Combina esto con Speculation Rules (arriba) para navegaciones instantáneas y animadas.

Scripts de terceros

Estrategias de carga

// ❌ Bloquea el hilo principal
<script src="https://analytics.example.com/script.js"></script>

// ✅ Carga asíncrona
<script async src="https://analytics.example.com/script.js"></script>

// ✅ Retrasar hasta la interacción
<script>
document.addEventListener('DOMContentLoaded', () => {
  const observer = new IntersectionObserver((entries) => {
    if (entries[0].isIntersecting) {
      const script = document.createElement('script');
      script.src = 'https://widget.example.com/embed.js';
      document.body.appendChild(script);
      observer.disconnect();
    }
  });
  observer.observe(document.querySelector('#widget-container'));
});
</script>

Patrón de fachada

<!-- Muestra un marcador de posición estático hasta la interacción -->
<div class="youtube-facade" 
     data-video-id="abc123" 
     onclick="loadYouTube(this)">
  <img src="/thumbnails/abc123.jpg" alt="Título del video">
  <button aria-label="Reproducir video">▶</button>
</div>

Medición

Usa el flujo de trabajo de medición cada vez que una URL sea ejecutable. Define el enrutamiento de Chrome DevTools MCP, las fuentes CrUX y de respaldo, las condiciones de laboratorio repetibles y un formato de evidencia compacto.

MétricaTipoInterpretación
LCP, INP, CLS en p75CampoCore Web Vitals de resultado de usuario; usar para priorización de aprobado/reprobado
LCP, CLS en una trazaLaboratorioValores de diagnóstico reproducibles para una navegación
TBTLaboratorioDiagnóstico de bloqueo del hilo principal y un proxy aproximado de INP, no INP de campo
FCP, Speed IndexLaboratorioDiagnósticos de carga, no Core Web Vitals

Los fragmentos sin procesar de PerformanceObserver son útiles para la sesión actual del navegador, pero no son datos de usuario reales por sí mismos. Cuando el usuario quiera telemetría de producción, lee la referencia de RUM de primera parte y prefiere web-vitals sobre una implementación de métrica hecha a mano.

Referencias

Para optimizaciones específicas de Core Web Vitals, consulta Core Web Vitals.

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

Skills relacionados