Introducción a la Optimización de Rendimiento
El rendimiento de una aplicación web se puede dividir en dos áreas principales:
- Mejorar la velocidad de carga
- Mejorar la velocidad de renderizado
A continuación, exploraremos técnicas para optimizar cada una de estas áreas.
Optimización de Carga
Para acelerar la carga de páginas, debemos enfocarnos en el tamaño de los recursos, el número de solicitudes y la red.
- Reducción del tamaño de recursos
- Compresión de código y activos
- Reducción del número de solicitudes
- Fusión de recursos
- Combinación de múltiples archivos JavaScript
- Combinación de múltiples archivos CSS
- Consolidación de pequeños iconos en una única imagen (spritesheet)
- Renderizado en el Servidor (SSR): Carga y renderizado simultáneo de página y datos
- La arquitectura frontend-back end tradicional carga primero la página, luego los datos y finalmente renderiza. Tecnologías como JSP y PHP implementaban SSR. Frameworks modernos como Vue y React también ofrecen SSR.
- Utilización de caché
- Adición de hashes a recursos estáticos para activar el mecanismo de caché HTTP y recibir respuestas 304 cuando el recurso no cambia
- Uso de redes más rápidas
- Redes de Distribución de Contenidos (CDN)
- Utilización de CDN para bibliotecas y recursos externos
Optimización de Renderizado
- Colocar CSS en el y JavaScript al final del
- Ejecutar JavaScript lo antes posible usando el evento DOMContentLoaded
<script>
document.addEventListener('DOMContentLoaded', function() {
// El DOM ha sido completamente cargado
// Las imágenes y otros recursos pueden no estar listos aún
inicializarAplicacion();
});
</script>
- Carga diferida de imágenes
- Implementar carga diferida para imágenes que apaercen en pantalla

<script>
document.addEventListener('DOMContentLoaded', function() {
const imagenes = document.querySelectorAll('.lazy-image');
const cargarImagenVisible = () => {
imagenes.forEach(img => {
const rect = img.getBoundingClientRect();
if (rect.top < window.innerHeight && rect.bottom > 0) {
img.src = img.dataset.src;
img.classList.remove('lazy-image');
}
});
};
cargarImagenVisible();
window.addEventListener('scroll', cargarImagenVisible);
});
</script>
- Caché de consultas DOM
// Sin caché de consultas DOM
const items = document.querySelectorAll('.item');
for (let i = 0; i < items.length; i++) {
// Cada iteración requiere una consulta DOM
items[i].classList.add('active');
}
// Con caché de consultas DOM
const items = document.querySelectorAll('.item');
const itemCount = items.length;
for (let i = 0; i < itemCount; i++) {
// Solo se realiza una consulta inicial
items[i].classList.add('active');
}
- Operaciones por lotes en DOM
const contenedor = document.getElementById('lista');
// Crear un fragmento de documento
const fragmento = document.createDocumentFragment();
// Generar elementos y añadirlos al fragmento
for (let i = 0; i < 20; i++) {
const elemento = document.createElement('div');
elemento.textContent = `Elemento ${i + 1}`;
fragmento.appendChild(elemento);
}
// Insertar todos los elementos de una sola vez
contenedor.appendChild(fragmento);
- Control de eventos con throttling y debouncing
- Debouncing
- Definición: Ejecutar la función después de que el evento no se haya disparado durante un período determinado
- Enfoque en el resultado final
- Aplicaciones:
- Búsqueda en tiempo real: Evitar búsquedas mientras el usuario sigue escribiendo
- Manejo de redimensionamiento de ventana: Ejceutar solo después de que el usuario termine de redimensionar
- Prevención de envíos múltiples: Evitar que se envíe un formulario múltiples veces
Implementación:
function debounce(funcionRetraso, tiempoEspera = 300) {
let temporizador = null;
return function(...argumentos) {
const contexto = this;
// Limpiar el temporizador existente
if (temporizador) {
clearTimeout(temporizador);
}
// Establecer un nuevo temporizador
temporizador = setTimeout(() => {
funcionRetraso.apply(contexto, argumentos);
temporizador = null;
}, tiempoEspera);
};
}
// Ejemplo de uso
const campoBusqueda = document.getElementById('campo-busqueda');
const realizarBusqueda = (evento) => {
console.log('Realizando búsqueda:', campoBusqueda.value);
};
campoBusqueda.addEventListener('input', debounce(realizarBusqueda, 500));
- Throttling
- Definición: Limitar la ejecución de una función a una vez cada ciertos intervalos de tiempo
- Enfoque en el proceso continuo
- Aplicaciones:
- Eventos de scroll: Limitar la frecuencia de actualizaciones durante el desplazamiento
- Animaciones suaves: Garantizar un número constante de actualizaciones por segundo
- Actualizaciones en tiempo real: Proporcionar retroalimentación sin sobrecargar el procesador
Implementación:
function throttle(funcionLimitada, intervaloTiempo) {
let ultimaEjecucion = 0;
return function(...argumentos) {
const contexto = this;
const ahora = Date.now();
if (ahora - ultimaEjecucion >= intervaloTiempo) {
funcionLimitada.apply(contexto, argumentos);
ultimaEjecucion = ahora;
}
};
}
// Ejemplo de uso
const elemento = document.getElementById 'elemento-desplazable';
const manejarScroll = (evento) => {
console.log('Posición actual:', window.scrollY);
};
window.addEventListener('scroll', throttle(manejarScroll, 200));