HTML5

HTML

Tutorial HTML: Optimización de la carga de la página (Lazy loading)

Aprende técnicas clave para optimizar la carga de páginas web con lazy loading y mejorar la experiencia y el SEO en sitios modernos.

Aprende HTML y certifícate

Técnicas para reducir el tiempo de carga

El tiempo de carga de una página web es un factor crítico para la experiencia del usuario. Estudios muestran que los usuarios tienden a abandonar sitios que tardan más de 3 segundos en cargar. Optimizar este aspecto no solo mejora la experiencia sino que también puede afectar positivamente el posicionamiento en buscadores.

Minificación de archivos

La minificación consiste en eliminar caracteres innecesarios del código sin alterar su funcionalidad. Esto incluye espacios en blanco, saltos de línea, comentarios y acortar nombres de variables cuando sea posible.

<!-- Antes de minificar -->
<div class="container">
    <h1>Bienvenidos a mi sitio web</h1>
    <!-- Este es un comentario explicativo -->
    <p>Este es un párrafo de ejemplo con mucho espacio.</p>
</div>

<!-- Después de minificar -->
<div class="container"><h1>Bienvenidos a mi sitio web</h1><p>Este es un párrafo de ejemplo con mucho espacio.</p></div>

Existen herramientas online y plugins para sistemas de construcción que automatizan este proceso.

Compresión de archivos

La compresión reduce el tamaño de los archivos que se envían al navegador. Los dos métodos más comunes son:

  • GZIP: Compresión estándar soportada por la mayoría de servidores y navegadores.
  • Brotli: Algoritmo más moderno que ofrece mejor ratio de compresión que GZIP.

Para implementar la compresión, se configura en el servidor web:

<!-- Ejemplo de configuración en .htaccess para Apache -->
<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript
</IfModule>

Optimización de imágenes

Las imágenes suelen representar la mayor parte del peso de una página web. Algunas técnicas para optimizarlas:

  • Redimensionar al tamaño exacto en que se mostrarán
  • Elegir el formato adecuado:
  • JPEG: para fotografías
  • PNG: para imágenes con transparencia
  • WebP: formato moderno con mejor compresión
  • AVIF: el más eficiente pero con menor compatibilidad
<!-- Uso de imagen WebP con fallback a JPEG -->
<picture>
  <source srcset="imagen.webp" type="image/webp">
  <img src="imagen.jpg" alt="Descripción de la imagen" width="800" height="600">
</picture>
  • Usar atributos width y height para evitar saltos de contenido durante la carga
  • Comprimir imágenes sin pérdida notable de calidad

Reducción de HTTP requests

Cada solicitud HTTP añade tiempo de carga. Algunas estrategias para reducirlas:

  • Combinar archivos CSS en uno solo
  • Combinar scripts JavaScript cuando sea posible
  • Usar sprites CSS para agrupar iconos pequeños
<!-- En lugar de cargar múltiples hojas de estilo -->
<link rel="stylesheet" href="estilos1.css">
<link rel="stylesheet" href="estilos2.css">
<link rel="stylesheet" href="estilos3.css">

<!-- Combinarlas en un solo archivo -->
<link rel="stylesheet" href="estilos-combinados.css">

Uso de CDN (Content Delivery Network)

Un CDN distribuye el contenido en servidores ubicados en diferentes regiones geográficas, permitiendo que los usuarios accedan a los recursos desde el servidor más cercano.

<!-- Uso de CDN para cargar una biblioteca -->
<script src="https://cdn.ejemplo.com/libreria.min.js"></script>

Beneficios:

  • Menor latencia para usuarios de diferentes ubicaciones
  • Distribución de carga entre servidores
  • Protección contra picos de tráfico

Optimización de fuentes web

Las fuentes personalizadas pueden aumentar significativamente el tiempo de carga. Para optimizarlas:

  • Limitar el número de variantes (pesos, estilos)
  • Usar el formato WOFF2 que ofrece mejor compresión
  • Implementar font-display para controlar cómo se muestran las fuentes durante la carga
<style>
  @font-face {
    font-family: 'MiFuente';
    src: url('mifuente.woff2') format('woff2');
    font-weight: normal;
    font-style: normal;
    font-display: swap;
  }
</style>

Optimización de CSS

El CSS puede bloquear el renderizado si no se maneja correctamente:

  • Colocar el CSS crítico en línea
  • Cargar hojas de estilo no críticas de forma asíncrona
<!-- CSS crítico en línea -->
<style>
  /* Estilos necesarios para el contenido visible inicialmente */
  body { margin: 0; font-family: sans-serif; }
  header { background: #f0f0f0; padding: 1rem; }
</style>

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

Optimización de JavaScript

El JavaScript puede bloquear el renderizado y la interactividad:

  • Usar atributos async o defer para scripts no críticos
  • Dividir el código (code splitting) para cargar solo lo necesario
  • Eliminar código no utilizado (tree shaking)
<!-- Script que no bloquea el renderizado -->
<script src="analytics.js" async></script>

<!-- Script que se ejecuta después del HTML -->
<script src="funciones.js" defer></script>

Implementación de caché

El caché permite almacenar recursos en el navegador para evitar descargarlos nuevamente:

  • Configurar encabezados Cache-Control adecuados
  • Implementar service workers para caché avanzado
<!-- Ejemplo de configuración en .htaccess -->
<IfModule mod_expires.c>
  ExpiresActive On
  ExpiresByType image/jpeg "access plus 1 year"
  ExpiresByType image/png "access plus 1 year"
  ExpiresByType text/css "access plus 1 month"
  ExpiresByType application/javascript "access plus 1 month"
</IfModule>

Priorización de recursos críticos

Usar atributos de precarga para indicar al navegador qué recursos son prioritarios:

<!-- Precargar recursos críticos -->
<link rel="preload" href="fuente-principal.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="imagen-hero.webp" as="image">
<link rel="preload" href="estilos-criticos.css" as="style">

Estas técnicas de optimización, aplicadas en conjunto, pueden reducir drásticamente los tiempos de carga de tu sitio web, mejorando tanto la experiencia de usuario como el posicionamiento en buscadores.

Carga diferida (lazy loading) de recursos

La carga diferida o lazy loading es una técnica de optimización que consiste en retrasar la carga de recursos no esenciales hasta que sean realmente necesarios. En lugar de cargar todo el contenido de una página de inmediato, los elementos se cargan solo cuando están a punto de entrar en el viewport (área visible de la pantalla).

Esta técnica es especialmente útil para sitios web con muchas imágenes, videos u otros contenidos pesados, ya que permite que la página inicial se cargue más rápidamente y consume menos datos para los usuarios.

Implementación nativa con atributo loading

HTML5 incorpora soporte nativo para lazy loading a través del atributo loading en elementos como imágenes e iframes:

<img src="imagen.jpg" alt="Descripción de la imagen" loading="lazy">

El atributo loading puede tener los siguientes valores:

  • lazy: Indica al navegador que retrase la carga hasta que el elemento esté cerca del viewport
  • eager: Carga inmediata (comportamiento predeterminado)
  • auto: Permite que el navegador decida la estrategia de carga

Este método nativo es la forma más sencilla de implementar lazy loading y tiene excelente compatibilidad con navegadores modernos.

Lazy loading para imágenes

Las imágenes son los candidatos perfectos para la carga diferida, ya que suelen ser los recursos más pesados:

<!-- Imagen con carga diferida -->
<img src="imagen.jpg" alt="Paisaje montañoso" loading="lazy" width="800" height="600">

Es importante incluir los atributos width y height para reservar el espacio necesario y evitar saltos de contenido cuando la imagen se cargue.

Para mejorar aún más la experiencia, podemos usar una imagen de baja resolución como placeholder:

<img 
  src="placeholder-pequeño.jpg" 
  data-src="imagen-grande.jpg" 
  alt="Paisaje montañoso" 
  loading="lazy"
  class="lazy-image"
  width="800" 
  height="600"
>

Con JavaScript podemos completar la implementación:

document.addEventListener("DOMContentLoaded", function() {
  const lazyImages = document.querySelectorAll(".lazy-image");
  
  // Opcional: para navegadores que no soportan loading="lazy"
  if ("IntersectionObserver" in window) {
    const imageObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          const image = entry.target;
          image.src = image.dataset.src;
          image.classList.remove("lazy-image");
          imageObserver.unobserve(image);
        }
      });
    });
    
    lazyImages.forEach(function(image) {
      imageObserver.observe(image);
    });
  } else {
    // Fallback para navegadores antiguos
    lazyImages.forEach(function(image) {
      image.src = image.dataset.src;
    });
  }
});

Lazy loading para iframes

Los iframes para contenido incrustado como mapas o videos también pueden beneficiarse de la carga diferida:

<iframe 
  src="about:blank" 
  data-src="https://www.youtube.com/embed/video_id" 
  loading="lazy"
  width="560" 
  height="315" 
  title="Video de YouTube"
  frameborder="0" 
  allowfullscreen
></iframe>

Con JavaScript podemos activar el iframe cuando sea necesario:

const lazyIframes = document.querySelectorAll("iframe[data-src]");
const iframeObserver = new IntersectionObserver(function(entries) {
  entries.forEach(function(entry) {
    if (entry.isIntersecting) {
      const iframe = entry.target;
      iframe.src = iframe.dataset.src;
      iframeObserver.unobserve(iframe);
    }
  });
});

lazyIframes.forEach(function(iframe) {
  iframeObserver.observe(iframe);
});

Lazy loading para videos

Los videos son recursos particularmente pesados que se benefician enormemente de la carga diferida:

<video 
  controls 
  width="800" 
  height="450" 
  poster="imagen-preview.jpg"
  preload="none">
  <source data-src="video.mp4" type="video/mp4">
  Tu navegador no soporta el elemento video.
</video>

El atributo preload="none" evita que el navegador precargue el video, y el atributo poster muestra una imagen mientras el video no se carga.

Lazy loading de contenido HTML

También podemos aplicar carga diferida a secciones enteras de HTML:

<div class="comentarios-container" data-lazy-load-url="/api/comentarios">
  <p>Cargando comentarios...</p>
</div>
const lazyContainers = document.querySelectorAll("[data-lazy-load-url]");
const containerObserver = new IntersectionObserver(function(entries) {
  entries.forEach(function(entry) {
    if (entry.isIntersecting) {
      const container = entry.target;
      const url = container.dataset.lazyLoadUrl;
      
      fetch(url)
        .then(response => response.text())
        .then(html => {
          container.innerHTML = html;
          containerObserver.unobserve(container);
        })
        .catch(error => {
          console.error("Error cargando contenido:", error);
          container.innerHTML = "Error al cargar el contenido.";
        });
    }
  });
});

lazyContainers.forEach(function(container) {
  containerObserver.observe(container);
});

Lazy loading de CSS y JavaScript

También podemos aplicar carga diferida a archivos CSS y JavaScript no críticos:

<!-- CSS con carga diferida -->
<link rel="preload" href="estilos-no-criticos.css" as="style" onload="this.onload=null;this.rel='stylesheet'">

<!-- JavaScript con carga diferida -->
<script>
  function loadScript(src) {
    const script = document.createElement('script');
    script.src = src;
    script.async = true;
    document.body.appendChild(script);
  }
  
  // Cargar script cuando el usuario interactúa
  document.querySelector('.boton-comentarios').addEventListener('click', function() {
    loadScript('/js/sistema-comentarios.js');
  });
</script>

Consideraciones importantes

Al implementar lazy loading, ten en cuenta estas recomendaciones:

  • Contenido visible: No apliques lazy loading a elementos que aparecen en la parte superior de la página (above the fold)
  • SEO: Asegúrate de que el contenido importante sea accesible para los motores de búsqueda
  • Accesibilidad: Proporciona alternativas para usuarios con JavaScript desactivado
  • Indicadores de carga: Muestra placeholders o esqueletos mientras el contenido se carga
  • Distancia de precarga: Configura la carga para que comience antes de que el elemento sea visible
<!-- Ejemplo con IntersectionObserver y rootMargin para precarga -->
<script>
  const options = {
    rootMargin: '200px 0px', // Comienza a cargar cuando el elemento está a 200px de ser visible
    threshold: 0
  };
  
  const imageObserver = new IntersectionObserver(callback, options);
</script>

La carga diferida es una técnica esencial en el desarrollo web moderno que, cuando se implementa correctamente, puede mejorar significativamente los tiempos de carga inicial, reducir el consumo de datos y proporcionar una mejor experiencia de usuario, especialmente en conexiones lentas o dispositivos móviles.

Priorización de contenido crítico

La priorización del contenido crítico es una estrategia fundamental para mejorar la percepción de velocidad en sitios web. Consiste en identificar y cargar primero los elementos esenciales que el usuario necesita ver inmediatamente, posponiendo todo lo demás para después.

El objetivo principal es optimizar el llamado "tiempo de primer renderizado significativo" (First Meaningful Paint), que representa el momento en que el usuario puede ver e interactuar con el contenido principal de la página.

Identificación del contenido crítico

Para implementar esta estrategia correctamente, primero debemos identificar qué elementos son realmente críticos:

  • Contenido visible en la primera pantalla (above the fold)
  • Elementos de navegación principales
  • Contenido que define la función principal de la página
  • Estilos necesarios para renderizar estos elementos

Todo lo demás puede considerarse no crítico y ser candidato para carga diferida o pospuesta.

CSS crítico en línea

Una de las técnicas más efectivas es incluir el CSS crítico directamente en el HTML, en lugar de cargarlo desde un archivo externo:

<head>
  <style>
    /* CSS crítico para el contenido visible inicialmente */
    body {
      margin: 0;
      font-family: 'Arial', sans-serif;
      color: #333;
    }
    header {
      background-color: #f8f9fa;
      padding: 1rem;
      box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    }
    .hero {
      height: 50vh;
      background: linear-gradient(45deg, #6a11cb, #2575fc);
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
    }
  </style>
  
  <!-- CSS no crítico cargado de forma asíncrona -->
  <link rel="stylesheet" href="styles.css" media="print" onload="this.media='all'">
</head>

Esta técnica elimina el bloqueo de renderizado causado por hojas de estilo externas, permitiendo que el contenido visible se muestre más rápidamente.

Priorización de scripts

El JavaScript puede bloquear significativamente el renderizado. Para priorizar correctamente:

  • Diferir scripts no críticos usando el atributo defer
  • Cargar de forma asíncrona scripts que no afecten el contenido inicial con async
  • Dividir el código en paquetes más pequeños (code splitting)
<!-- Script crítico que debe ejecutarse inmediatamente -->
<script>
  // Código mínimo necesario para la funcionalidad inicial
  document.querySelector('.toggle-menu').addEventListener('click', function() {
    document.querySelector('nav').classList.toggle('visible');
  });
</script>

<!-- Script importante pero que puede esperar a que se analice el HTML -->
<script src="main.js" defer></script>

<!-- Script no crítico que puede cargarse de forma asíncrona -->
<script src="analytics.js" async></script>

Uso de atributos de precarga

HTML ofrece varios atributos que permiten indicar al navegador qué recursos debe priorizar:

  • preload: Indica al navegador que cargue un recurso lo antes posible
  • prefetch: Sugiere cargar un recurso que probablemente se necesitará pronto
  • preconnect: Establece conexiones anticipadas a dominios externos
  • dns-prefetch: Resuelve nombres de dominio anticipadamente
<!-- Precargar recursos críticos -->
<link rel="preload" href="fuente-principal.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="hero-image.webp" as="image">

<!-- Preconectar a dominios externos -->
<link rel="preconnect" href="https://api.example.com">
<link rel="dns-prefetch" href="https://cdn.example.com">

<!-- Prefetch para navegación probable -->
<link rel="prefetch" href="pagina-siguiente.html">

Es importante usar estos atributos con moderación y solo para recursos realmente necesarios, ya que un uso excesivo puede sobrecargar la red y ralentizar la carga inicial.

Priorización de imágenes críticas

Las imágenes suelen ser los recursos más pesados. Para priorizar correctamente:

  • Precargar imágenes críticas que aparecen en la primera pantalla
  • Usar imágenes responsive con el elemento <picture> y srcset
  • Implementar imágenes progresivas que se muestran gradualmente
<!-- Precargar imagen crítica -->
<link rel="preload" as="image" href="hero.webp">

<!-- Imagen responsive con priorización -->
<picture>
  <source media="(min-width: 800px)" srcset="hero-large.webp" type="image/webp">
  <source media="(min-width: 400px)" srcset="hero-medium.webp" type="image/webp">
  <img src="hero-small.webp" alt="Imagen principal" width="1200" height="600" fetchpriority="high">
</picture>

El atributo fetchpriority="high" (disponible en navegadores modernos) indica explícitamente que esta imagen debe tener alta prioridad de carga.

Priorización con HTTP/2 Server Push

Si tu servidor soporta HTTP/2, puedes utilizar Server Push para enviar recursos críticos al navegador antes de que los solicite:

<!-- En el servidor (ejemplo para Apache) -->
<IfModule mod_headers.c>
  <FilesMatch "index.html">
    Header add Link "</css/critical.css>; rel=preload; as=style"
    Header add Link "</js/critical.js>; rel=preload; as=script"
  </FilesMatch>
</IfModule>

Esta técnica debe usarse con precaución, ya que puede interferir con la caché del navegador si no se implementa correctamente.

Estrategias de renderizado progresivo

Para mejorar la percepción de velocidad, podemos implementar técnicas de renderizado progresivo:

  • Esqueletos de carga (skeleton screens) que muestran la estructura de la página
  • Carga progresiva de contenido por secciones
  • Renderizado por lotes para listas largas
<!-- Esqueleto de carga -->
<div class="card skeleton">
  <div class="skeleton-image"></div>
  <div class="skeleton-title"></div>
  <div class="skeleton-text"></div>
</div>

<style>
  .skeleton {
    background: #f0f0f0;
    position: relative;
    overflow: hidden;
  }
  
  .skeleton::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
    animation: loading 1.5s infinite;
  }
  
  @keyframes loading {
    100% {
      transform: translateX(100%);
    }
  }
</style>

Optimización de fuentes web

Las fuentes web pueden causar retrasos significativos. Para priorizar correctamente:

  • Precargar fuentes críticas
  • Usar font-display para controlar el comportamiento durante la carga
  • Considerar fuentes del sistema como fallback inicial
<!-- Precargar fuente crítica -->
<link rel="preload" href="fonts/main.woff2" as="font" type="font/woff2" crossorigin>

<style>
  @font-face {
    font-family: 'MainFont';
    src: url('fonts/main.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
  }
  
  body {
    /* Cascada de fuentes con alternativas del sistema */
    font-family: 'MainFont', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
  }
</style>

El valor swap en font-display permite que el texto se muestre inmediatamente con una fuente alternativa mientras se carga la fuente personalizada.

Herramientas para identificar contenido crítico

Para identificar correctamente qué contenido priorizar, puedes utilizar:

  • Chrome DevTools: Panel de rendimiento y cobertura
  • Lighthouse: Para análisis de rendimiento y recomendaciones
  • WebPageTest: Para análisis detallado de la cascada de carga

Estas herramientas te ayudarán a identificar qué recursos están bloqueando el renderizado y cuáles deberían priorizarse.

Implementación práctica

Un enfoque completo para priorizar contenido crítico podría verse así:

<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Mi Sitio Web Optimizado</title>
  
  <!-- Preconexiones a dominios externos -->
  <link rel="preconnect" href="https://fonts.googleapis.com">
  
  <!-- CSS crítico en línea -->
  <style>
    /* Estilos mínimos para el contenido visible inicialmente */
    body { margin: 0; font-family: sans-serif; line-height: 1.5; }
    header { padding: 1rem; background: #f8f9fa; }
    .hero { height: 60vh; display: flex; align-items: center; justify-content: center; }
    .hero h1 { font-size: 2.5rem; margin-bottom: 1rem; }
    .btn { display: inline-block; padding: 0.5rem 1rem; background: #0066cc; color: white; text-decoration: none; }
  </style>
  
  <!-- Precargar imagen crítica -->
  <link rel="preload" as="image" href="hero.webp">
  
  <!-- CSS no crítico -->
  <link rel="stylesheet" href="styles.css" media="print" onload="this.media='all'">
  <noscript><link rel="stylesheet" href="styles.css"></noscript>
</head>
<body>
  <header>
    <nav>
      <a href="/">Inicio</a>
      <a href="/productos">Productos</a>
      <a href="/contacto">Contacto</a>
    </nav>
  </header>
  
  <main>
    <section class="hero">
      <div>
        <h1>Bienvenido a nuestro sitio</h1>
        <p>Ofrecemos soluciones innovadoras para tu negocio</p>
        <a href="/productos" class="btn">Ver productos</a>
      </div>
    </section>
    
    <!-- Contenido no crítico con carga diferida -->
    <section class="features" data-load-content="/api/features">
      <div class="skeleton-features">
        <!-- Esqueletos de carga -->
      </div>
    </section>
  </main>
  
  <!-- Script crítico -->
  <script>
    // Código mínimo para funcionalidad inicial
    document.addEventListener('DOMContentLoaded', function() {
      // Cargar contenido no crítico
      const featuresSection = document.querySelector('.features');
      if (featuresSection) {
        fetch(featuresSection.dataset.loadContent)
          .then(response => response.text())
          .then(html => {
            featuresSection.innerHTML = html;
          });
      }
    });
  </script>
  
  <!-- Scripts no críticos -->
  <script src="main.js" defer></script>
  <script src="analytics.js" async></script>
</body>
</html>

La priorización de contenido crítico, cuando se implementa correctamente, puede mejorar drásticamente la percepción de velocidad de tu sitio web, incluso en conexiones lentas o dispositivos con recursos limitados. El enfoque debe ser siempre mostrar el contenido útil lo más rápido posible, posponiendo todo lo demás para después de que la página sea interactiva.

Medición de rendimiento con herramientas de desarrollo

Para optimizar efectivamente el rendimiento de carga de un sitio web, es fundamental contar con datos objetivos que nos permitan identificar problemas específicos y medir el impacto de nuestras mejoras. Los navegadores modernos incluyen potentes herramientas de desarrollo que facilitan este análisis.

Chrome DevTools: Panel de rendimiento

El panel Performance (Rendimiento) de Chrome DevTools es una de las herramientas más completas para analizar el rendimiento de carga:

  1. Para acceder a él:
  • Abre Chrome DevTools con F12 o Ctrl+Shift+I (Cmd+Option+I en Mac)
  • Selecciona la pestaña "Performance"
// Ejemplo de cómo medir rendimiento desde JavaScript
performance.mark('inicio-carga');

// Código que queremos medir
cargarRecursos();

performance.mark('fin-carga');
performance.measure('tiempo-carga', 'inicio-carga', 'fin-carga');

Al realizar una grabación en el panel de rendimiento, obtendrás una línea de tiempo detallada que muestra:

  • FCP (First Contentful Paint): Momento en que se muestra el primer contenido
  • LCP (Largest Contentful Paint): Cuando se renderiza el contenido principal
  • TTI (Time to Interactive): Momento en que la página se vuelve interactiva
  • Bloqueos del hilo principal: Operaciones que retrasan la interactividad

Lighthouse: Análisis integral

Lighthouse es una herramienta de auditoría automatizada integrada en Chrome DevTools que proporciona informes detallados sobre:

  • Rendimiento
  • Accesibilidad
  • Mejores prácticas
  • SEO
  • PWA (Progressive Web App)

Para ejecutar Lighthouse:

  1. Abre DevTools
  2. Selecciona la pestaña "Lighthouse"
  3. Selecciona las categorías que deseas analizar
  4. Haz clic en "Generate report"

El informe de rendimiento incluye métricas clave como:

  • Performance Score: Puntuación global de 0 a 100
  • Oportunidades de mejora: Sugerencias específicas con ahorro estimado
  • Diagnósticos: Información adicional sobre el rendimiento
<!-- Ejemplo de mejora sugerida por Lighthouse -->
<!-- Antes -->
<img src="imagen-grande.jpg" alt="Descripción">

<!-- Después (con dimensiones explícitas y lazy loading) -->
<img src="imagen-grande.jpg" alt="Descripción" width="800" height="600" loading="lazy">

Network Panel: Análisis de recursos

El panel Network (Red) permite analizar en detalle cada solicitud HTTP realizada por la página:

  1. Activa la grabación de red antes de cargar la página
  2. Recarga la página para capturar todas las solicitudes
  3. Examina la cascada de carga y los tiempos de cada recurso

Información clave que proporciona:

  • Waterfall (Cascada): Visualización de la secuencia y duración de las solicitudes
  • Tiempo de inicio: Cuándo comienza cada solicitud
  • Tiempo de bloqueo: Tiempo esperando antes de iniciar la descarga
  • Tiempo de TTFB: Time To First Byte (latencia del servidor)
  • Tiempo de contenido: Duración de la descarga

Para identificar cuellos de botella:

  • Ordena por tamaño para encontrar recursos demasiado grandes
  • Busca recursos con alto tiempo de espera (waiting)
  • Identifica recursos que bloquean el renderizado
<!-- Ejemplo de recurso que podría optimizarse tras análisis -->
<script>
  // Antes: Carga síncrona que bloquea el renderizado
  document.write('<script src="analytics.js"><\/script>');
  
  // Después: Carga asíncrona que no bloquea
  window.addEventListener('load', function() {
    const script = document.createElement('script');
    script.src = 'analytics.js';
    document.body.appendChild(script);
  });
</script>

Web Vitals: Métricas centradas en el usuario

Las Core Web Vitals son métricas estandarizadas por Google que miden aspectos clave de la experiencia del usuario:

  • LCP (Largest Contentful Paint): Mide el tiempo de carga percibido
  • FID (First Input Delay): Mide la interactividad
  • CLS (Cumulative Layout Shift): Mide la estabilidad visual

Chrome DevTools muestra estas métricas en el panel Performance, y también puedes medirlas con la API web-vitals:

<script type="module">
  import {getLCP, getFID, getCLS} from 'https://unpkg.com/web-vitals?module';

  function enviarMetricas({name, value}) {
    console.log(`${name}: ${value}`);
    // Aquí podrías enviar los datos a un servicio de análisis
  }

  // Medir las Core Web Vitals
  getCLS(enviarMetricas);
  getFID(enviarMetricas);
  getLCP(enviarMetricas);
</script>

Los valores ideales para estas métricas son:

  • LCP: menos de 2.5 segundos
  • FID: menos de 100 milisegundos
  • CLS: menos de 0.1

Coverage Panel: Análisis de código no utilizado

El panel Coverage (Cobertura) permite identificar código no utilizado en CSS y JavaScript:

  1. Abre DevTools y presiona Ctrl+Shift+P (Cmd+Shift+P en Mac)
  2. Escribe "Show Coverage" y selecciona la opción
  3. Haz clic en el botón de recarga para iniciar el análisis

Este panel muestra:

  • Porcentaje de código utilizado vs. no utilizado
  • Visualización línea por línea del código usado/no usado
<!-- Ejemplo de mejora basada en análisis de cobertura -->
<!-- Antes: Cargando toda la biblioteca -->
<script src="framework-completo.js"></script>

<!-- Después: Cargando solo los componentes necesarios -->
<script src="framework-core.js"></script>
<script src="framework-componente-a.js"></script>
<script src="framework-componente-b.js"></script>

Performance API: Medición programática

La Performance API permite medir el rendimiento desde JavaScript, lo que facilita la recopilación de datos reales de usuarios:

// Medir tiempo de navegación
const navData = performance.getEntriesByType('navigation')[0];
console.log(`Tiempo de carga DOM: ${navData.domComplete}ms`);
console.log(`Tiempo total de carga: ${navData.loadEventEnd}ms`);

// Medir tiempo de recursos
const recursos = performance.getEntriesByType('resource');
recursos.forEach(recurso => {
  if (recurso.initiatorType === 'img') {
    console.log(`Imagen ${recurso.name}: ${Math.round(recurso.duration)}ms`);
  }
});

// Crear marcas y medidas personalizadas
performance.mark('inicio-animacion');
// Ejecutar animación
performance.mark('fin-animacion');
performance.measure('duracion-animacion', 'inicio-animacion', 'fin-animacion');

const medidas = performance.getEntriesByType('measure');
console.log(`La animación tardó ${medidas[0].duration}ms`);

WebPageTest: Análisis en condiciones reales

WebPageTest es una herramienta externa que permite probar el rendimiento en diferentes ubicaciones, dispositivos y condiciones de red:

  1. Visita webpagetest.org
  2. Ingresa la URL de tu sitio
  3. Configura las condiciones de prueba (ubicación, navegador, velocidad de conexión)
  4. Ejecuta la prueba

WebPageTest proporciona:

  • Waterfall view: Cascada detallada de carga de recursos
  • Filmstrip view: Capturas de pantalla secuenciales durante la carga
  • Content breakdown: Análisis del peso por tipo de contenido
  • Request details: Información detallada de cada solicitud

Análisis de carga diferida

Para evaluar la efectividad de la implementación de lazy loading, podemos usar:

  1. Panel Network con throttling: Simula conexiones lentas para ver el comportamiento
  2. Scroll lento: Observa cómo se cargan los recursos al hacer scroll
  3. Conteo de solicitudes iniciales: Verifica cuántas solicitudes se realizan al cargar la página
<!-- Ejemplo para probar carga diferida de imágenes -->
<div style="height: 2000px; padding-top: 100px;">
  <img src="placeholder.jpg" data-src="imagen-real.jpg" loading="lazy" 
       onload="if(this.src.includes('real')) console.log('Imagen cargada:', performance.now())">
</div>

<script>
  // Registrar tiempo inicial
  console.log('Tiempo inicial:', performance.now());
  
  // Observar cuándo la imagen entra en el viewport
  const observer = new IntersectionObserver(entries => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        console.log('Imagen visible:', performance.now());
        const img = entry.target;
        img.src = img.dataset.src;
        observer.unobserve(img);
      }
    });
  });
  
  document.querySelectorAll('img[data-src]').forEach(img => {
    observer.observe(img);
  });
</script>

Interpretación de resultados y mejora continua

El análisis de rendimiento no es una tarea puntual sino un proceso continuo:

  1. Establecer línea base: Medir el rendimiento actual
  2. Identificar problemas: Usar las herramientas para detectar cuellos de botella
  3. Implementar mejoras: Aplicar técnicas de optimización
  4. Medir impacto: Comparar con la línea base
  5. Iterar: Repetir el proceso

Es recomendable crear un dashboard de rendimiento que monitoree las métricas clave a lo largo del tiempo, especialmente después de cada despliegue.

// Ejemplo de código para monitoreo continuo de Web Vitals
import {getLCP, getFID, getCLS} from 'web-vitals';

function enviarAnalytics(metric) {
  const body = {
    name: metric.name,
    value: metric.value,
    id: 'ID-USUARIO',
    page: window.location.pathname,
    timestamp: Date.now()
  };
  
  // Enviar a servicio de análisis
  navigator.sendBeacon('/analytics', JSON.stringify(body));
}

getLCP(enviarAnalytics);
getFID(enviarAnalytics);
getCLS(enviarAnalytics);

Estas herramientas de desarrollo proporcionan los datos necesarios para tomar decisiones informadas sobre optimización de rendimiento. Al combinar el análisis técnico con métricas centradas en el usuario, podemos crear experiencias web que no solo sean técnicamente eficientes sino también satisfactorias para los usuarios finales.

Aprende HTML online

Otros ejercicios de programación de HTML

Evalúa tus conocimientos de esta lección Optimización de la carga de la página (Lazy loading) con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Todas las lecciones de HTML

Accede a todas las lecciones de HTML y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Accede GRATIS a HTML y certifícate

En esta lección

Objetivos de aprendizaje de esta lección

  • Comprender diversas técnicas para reducir el tiempo de carga de una página web.
  • Implementar carga diferida (lazy loading) para imágenes, iframes, videos y contenido HTML.
  • Priorizar contenido crítico para mejorar el tiempo de primer renderizado significativo.
  • Utilizar herramientas de desarrollo para medir y analizar el rendimiento de carga.
  • Aplicar buenas prácticas para optimizar CSS, JavaScript, imágenes y fuentes web.