Puntos clave
1. Carga JavaScript de manera eficiente para reducir solicitudes HTTP y mejorar la velocidad de la página
Reduce el número de solicitudes HTTP necesarias para renderizar la página.
Combina y posiciona scripts. Fusiona múltiples archivos JavaScript en un solo archivo para minimizar las solicitudes HTTP. Coloca las etiquetas de script al final del cuerpo HTML para permitir que la página se cargue visualmente antes de ejecutar los scripts. Utiliza técnicas de carga asíncrona como la inserción dinámica de scripts o el atributo defer cuando sea posible.
Minimiza y comprime. Usa herramientas como YUI Compressor para eliminar caracteres innecesarios y espacios en blanco de los archivos JavaScript. Habilita la compresión gzip en tu servidor web para reducir aún más el tamaño de los archivos. Considera usar una Red de Distribución de Contenidos (CDN) para servir activos estáticos, incluidos los archivos JavaScript, desde servidores distribuidos geográficamente para una entrega más rápida.
Implementa estrategias de caché. Establece encabezados de caché apropiados para los archivos JavaScript para permitir que los navegadores los almacenen localmente. Usa versionado o marcas de tiempo en los nombres de archivo para forzar actualizaciones cuando sea necesario. Para dispositivos móviles con capacidades de caché limitadas, considera usar caché de aplicaciones HTML5 o mecanismos de almacenamiento del lado del cliente.
2. Optimiza el acceso a datos y la gestión de alcance para una ejecución más rápida
Las variables locales siempre son las más rápidas de acceder dentro de una función, mientras que las variables globales generalmente son las más lentas.
Minimiza la travesía de la cadena de alcance. Almacena variables fuera de alcance que se acceden con frecuencia en variables locales. Evita usar la declaración with y eval(), ya que pueden extender la cadena de alcance y ralentizar la ejecución. Usa cierres con prudencia, ya que mantienen referencias a su alcance exterior y pueden afectar el uso de memoria.
Optimiza el acceso a objetos y arreglos. Usa notación de punto en lugar de notación de corchetes al acceder a propiedades de objetos con identificadores conocidos y válidos. Almacena en caché la longitud de los arreglos en bucles for para evitar búsquedas repetidas de propiedades. Considera usar objetos o arreglos simples en lugar de estructuras de datos más complejas cuando el almacenamiento de clave-valor simple sea suficiente.
Aprovecha la notación literal. Usa literales de objetos y arreglos en lugar de sus contrapartes constructoras (por ejemplo, {} en lugar de new Object()). Esto no solo mejora la legibilidad, sino que también puede ser más rápido en muchos motores de JavaScript.
3. Minimiza la manipulación del DOM para mejorar el rendimiento
El acceso y la manipulación del DOM son una parte importante de las aplicaciones web modernas. Pero cada vez que cruzas el puente de ECMAScript a la tierra del DOM, tiene un costo.
Agrupa operaciones del DOM. Minimiza la manipulación directa del DOM haciendo cambios en un fragmento de documento o nodo clonado antes de actualizar el DOM en vivo. Esto reduce el número de reflujo y repintado, que son computacionalmente costosos.
Usa selectores eficientes. Aprovecha los métodos nativos del DOM como getElementById() y querySelector() en lugar de métodos más genéricos. Al usar bibliotecas, asegúrate de que utilicen estos métodos nativos más rápidos cuando estén disponibles. Almacena en caché las referencias del DOM para elementos que se acceden con frecuencia.
Optimiza el manejo de eventos. Implementa la delegación de eventos adjuntando oyentes de eventos a elementos padre en lugar de elementos hijos individuales. Esto reduce el número de oyentes de eventos y mejora el rendimiento, especialmente para elementos añadidos dinámicamente.
4. Implementa algoritmos eficientes y técnicas de control de flujo
En realidad, solo hay dos factores: el trabajo realizado por iteración y el número de iteraciones.
Optimiza los bucles. Minimiza el trabajo realizado en cada iteración moviendo el código invariante fuera del bucle. Usa bucles while inversos cuando sea posible, ya que a menudo son más rápidos que los bucles for. Considera usar métodos de arreglo como forEach(), map() y reduce() para iteraciones más limpias y potencialmente más rápidas.
Elige condicionales apropiados. Usa declaraciones switch en lugar de largas cadenas if-else al tratar con múltiples valores discretos. Para condiciones complejas, considera usar tablas de búsqueda o máscaras de bits para una evaluación más rápida.
Implementa memoización. Almacena en caché los resultados de llamadas a funciones costosas para evitar cálculos redundantes. Esto es especialmente útil para funciones recursivas u operaciones que se llaman con frecuencia con las mismas entradas.
5. Elige el formato de datos adecuado para un rendimiento óptimo de Ajax
JSON tiene varias ventajas en comparación con XML. Es un formato mucho más pequeño, con menos del tamaño total de la respuesta utilizado como estructura y más como datos.
Prefiere JSON sobre XML. JSON es más compacto y más rápido de analizar que XML. Cuando sea posible, usa JSON-P (JSON con padding) para un análisis aún más rápido, especialmente al tratar con grandes conjuntos de datos. Para conjuntos de datos extremadamente grandes, considera usar formatos delimitados personalizados para un mínimo de sobrecarga.
Optimiza la transmisión de datos. Usa solicitudes GET para operaciones idempotentes y POST para cargas útiles más grandes. Implementa estrategias de caché adecuadas para respuestas Ajax para reducir solicitudes de red innecesarias. Considera usar técnicas como XHR multipart para agrupar múltiples recursos en una sola solicitud.
Maneja los datos de manera eficiente. Analiza las respuestas JSON usando métodos nativos como JSON.parse() cuando estén disponibles. Implementa el renderizado progresivo para grandes conjuntos de datos para mejorar el rendimiento percibido. Usa trabajadores web para tareas de análisis o procesamiento que consumen mucho tiempo para mantener la interfaz de usuario receptiva.
6. Crea interfaces receptivas gestionando el hilo de la interfaz de usuario del navegador
Ninguna tarea de JavaScript debería tardar más de 100 milisegundos en ejecutarse.
Divide tareas de larga duración. Usa setTimeout() o setInterval() para dividir operaciones largas en fragmentos más pequeños, permitiendo que la interfaz de usuario permanezca receptiva. Considera usar Web Workers para tareas intensivas en CPU que no requieren acceso al DOM.
Optimiza los manejadores de eventos. Debounce o throttle los manejadores de eventos para eventos frecuentes como desplazamiento o cambio de tamaño para reducir el número de llamadas a funciones. Asegúrate de que los manejadores de eventos se completen rápidamente, especialmente para interacciones del usuario.
Gestiona animaciones de manera eficiente. Usa requestAnimationFrame() para animaciones más suaves que están sincronizadas con el ciclo de renderizado del navegador. Minimiza el número de elementos que se animan y usa transiciones o animaciones CSS cuando sea posible para un mejor rendimiento.
7. Aprovecha los procesos de construcción y despliegue para mejorar el rendimiento de JavaScript
Todo lo que se pueda hacer en tiempo de construcción no debería hacerse en tiempo de ejecución.
Automatiza las optimizaciones. Implementa un proceso de construcción usando herramientas como Grunt, Gulp o Webpack para automatizar tareas como concatenación, minificación y compresión de archivos JavaScript. Usa mapas de origen para mantener la capacidad de depuración del código minificado.
Implementa la división de código. Divide tu aplicación en fragmentos más pequeños que se puedan cargar bajo demanda, reduciendo la carga inicial y mejorando el tiempo de inicio. Usa técnicas como la carga diferida para recursos no críticos.
Optimiza para producción. Elimina el código solo para desarrollo, como declaraciones de registro y depuración, en compilaciones de producción. Implementa detección de características en lugar de detección de navegadores para crear un código más mantenible y de mejor rendimiento en diferentes entornos.
8. Utiliza herramientas de perfilado para identificar y resolver cuellos de botella de rendimiento
Tener el software adecuado es esencial para identificar cuellos de botella tanto en la carga como en la ejecución de scripts.
Aprovecha las herramientas de desarrollo del navegador. Usa los perfiles integrados en navegadores como Chrome DevTools, Firefox Developer Tools y Safari Web Inspector para analizar el tiempo de ejecución de JavaScript e identificar funciones lentas. Utiliza paneles de red para optimizar la carga de recursos e identificar cuellos de botella en la entrega de activos.
Implementa temporización personalizada. Usa la API de rendimiento (window.performance) o funciones de temporización personalizadas para medir operaciones específicas en tu código. Esto permite un seguimiento y optimización del rendimiento más granular.
Monitorea el rendimiento en el mundo real. Implementa el Monitoreo de Usuario Real (RUM) para recopilar datos de rendimiento de usuarios reales. Esto proporciona información sobre cómo se desempeña tu aplicación en diferentes dispositivos y condiciones de red, ayudando a priorizar los esfuerzos de optimización.
Última actualización:
Reseñas
JavaScript de Alto Rendimiento recibe opiniones mixtas, con una calificación promedio de 4.11 sobre 5. Muchos lectores elogian sus detalladas perspectivas y consejos prácticos para optimizar el código JavaScript. Sin embargo, algunos critican su contenido desactualizado, ya que el libro fue publicado en 2010. Los aspectos positivos incluyen explicaciones exhaustivas de técnicas de rendimiento, interacciones con el DOM y expresiones regulares. Los críticos señalan que muchas prácticas ahora son estándar y que los puntos de referencia de los navegadores están obsoletos. A pesar de su antigüedad, algunos lectores aún encuentran valor en los fundamentos y la perspectiva histórica sobre la optimización del rendimiento de JavaScript.