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ícateTé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>
ysrcset
- 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:
- 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:
- Abre DevTools
- Selecciona la pestaña "Lighthouse"
- Selecciona las categorías que deseas analizar
- 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:
- Activa la grabación de red antes de cargar la página
- Recarga la página para capturar todas las solicitudes
- 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:
- Abre DevTools y presiona Ctrl+Shift+P (Cmd+Shift+P en Mac)
- Escribe "Show Coverage" y selecciona la opción
- 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:
- Visita webpagetest.org
- Ingresa la URL de tu sitio
- Configura las condiciones de prueba (ubicación, navegador, velocidad de conexión)
- 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:
- Panel Network con throttling: Simula conexiones lentas para ver el comportamiento
- Scroll lento: Observa cómo se cargan los recursos al hacer scroll
- 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:
- Establecer línea base: Medir el rendimiento actual
- Identificar problemas: Usar las herramientas para detectar cuellos de botella
- Implementar mejoras: Aplicar técnicas de optimización
- Medir impacto: Comparar con la línea base
- 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.
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.
Reto etiquetas semánticas HTML
Divisiones
Reto atributos ARIA en HTML
Reto trabajar con imágenes en HTML
Formularios
Encabezados
Reto metadatos en HTML
Validación de HTML
Navegación por teclado
Párrafos
Uso de DOCTYPE
Etiquetas semánticas
Contraste y legibilidad
Atributos
Reto formatear texto en HTML
Reto crear listas HTML
Metadatos
Comentarios
Incrustación de contenido (iframe)
Uso de elementos y etiquetas
Audio
Proyecto crear páginas HTML
Enlace
Video
Imágenes
DOCTYPE
Compatibilidad con navegadores
Reto crear tablas HTML
Introducción a HTML
Imágenes vectoriales
Anidación de etiquetas
Reto Validación HTML
Optimización de la carga de la página (Lazy loading)
Listas
Estilos
Reto de enlaces HTML
Atributos de ARIA
Reto geolocalización en HTML
Tablas
Reto LocalStorage en HTML
Uso de atributos
Elementos y etiquetas
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.
Introducción A Html
Introducción Y Entorno
Doctype
Sintaxis Y Estructura
Elementos Y Etiquetas
Sintaxis Y Estructura
Atributos
Sintaxis Y Estructura
Anidación De Etiquetas
Sintaxis Y Estructura
Comentarios
Sintaxis Y Estructura
Encabezados (H1-h6)
Textos Y Enlaces
Enlace (A)
Textos Y Enlaces
Párrafo (P)
Textos Y Enlaces
Listas (Ul, Ol, Li)
Textos Y Enlaces
Imagen (Img)
Textos Y Enlaces
División (Div)
Organización De Contenido
Etiquetas Semánticas (Article, Section, Header, Footer, Nav, Aside)
Organización De Contenido
Tablas (Table, Tr, Td, Th)
Organización De Contenido
Formularios (Form, Input, Select, Textarea, Button)
Organización De Contenido
Imágenes Vectoriales (Svg)
Elementos Multimedia
Incrustación De Contenido (Iframe)
Elementos Multimedia
Audio (Audio)
Elementos Multimedia
Video (Video)
Elementos Multimedia
Estilo Incorporado (Style)
Metadatos Y Seo
Metadatos (Meta, Title, Link)
Metadatos Y Seo
Atributos De Aria
Metadatos Y Seo
Navegación Por Teclado
Metadatos Y Seo
Contraste Y Legibilidad
Optimización Html
Validación De Html
Optimización Html
Compatibilidad Con Navegadores
Optimización Html
Optimización De La Carga De La Página (Lazy Loading)
Optimización Html
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.