Optimización de activos de JavaScript para la velocidad de la página

Publicado: 2020-05-05

El siguiente ejemplo es de un sitio web de noticias grande y complejo. Llevan años perdiendo tráfico orgánico. Su tiempo de evento DOMContentLoaded es 2615.2 MS. Puedes pensar que el tamaño de su DOM es extremadamente grande, pero no...

Es casi lo mismo que recomienda Google, y solo existen 1230 nodos HTML en este documento.

Puede calcular el tiempo y el proceso de su evento domContentLoaded y compararlo con sus competidores usando DevTools.

El examen de este ejemplo muestra que el tamaño del DOM no es necesariamente el punto crítico. Aquí, el principal problema es el orden de los recursos : las partes azules en la "Pestaña principal" son para el análisis de HTML. Sin embargo, este sitio web interrumpe el navegador con la representación de JavaScript antes de que finalice el proceso de análisis de HTML.

(También puede usar la sección Árbol de llamadas para ayudar a encontrar errores similares para su equipo de TI).

Este ejemplo ilustra claramente la importancia de optimizar los activos de JavaScript y lo que puede salir mal cuando descuida JavaScript en las optimizaciones de velocidad de su página.

Este es el tercero de una serie de cuatro artículos. Para comprender mejor este artículo, es posible que desee leer los dos primeros artículos de la serie:

  • La representación de Javascript y la velocidad de la página están estrechamente relacionadas con la forma en que el motor de representación de un navegador crea una página web.
  • También debe comprender las métricas avanzadas de velocidad de página antes de entrar en este artículo.

Usaré algunos ejemplos de los primeros dos artículos para ayudar a proporcionar contexto en este.

¿Qué es Javascript Rendering y cómo afecta la velocidad de tu página?

La representación de Javascript es la última sección de carga de la página que puede cambiar de forma interactiva la estructura creada con DOM y CSSOM. Cualquier elemento de la página se puede cambiar en un formato activado por el usuario o se puede mostrar como normal. Cualquier elemento con una propiedad display:none a la que no se pueda acceder mediante el árbol de representación puede hacerse visible con JavaScript o inyectarse a través de diferentes elementos HTML en el DOM.

JavaScript interrumpe el DOM y el CSSOM porque cambia el DOM y el CSSOM en el momento en que el navegador los lee. Por lo tanto, para evitar que afecte negativamente el tiempo y la velocidad de carga de la página, es necesario examinar la relación entre DOM, CSSOM y la representación de JavaScript.

Arriba hay un ejemplo de un árbol de representación. Todos los fragmentos de código entrelazados en los nodos CSSOM y HTML tienen equivalentes semánticos en el árbol de representación. Si observa detenidamente, notará que el nodo HTML "Botón de acción" no está en el árbol de representación. La razón principal de esto es “display:none;” Propiedad CSS. Debido a este comando de invisibilidad, no se incluye en el árbol de representación. Para ver cómo se construyeron los elementos de este árbol, quizás desee leer el primer artículo de esta serie.

Si tiene muchos elementos de página que no aparecerán en la primera carga porque dependen del comportamiento del usuario, en el orden de carga de recursos, deberá separar estos elementos y colocarlos en la última fila. Usar un DOM en la sombra o un DOM virtual son mejores opciones en este punto.

Atributos diferidos y asíncronos para recursos de JavaScript

Si coloca sus archivos JS en la sección y si no usa los atributos 'diferir' o 'async', probablemente retrasará su tiempo de carga de contenido DOM. Para evitar esta situación, podemos usar estos dos atributos. Aplazar es retrasar el proceso de carga de un archivo JS mientras que 'Async' es cargar JS y otras fuentes de forma paralela. Ambos tienen ventajas y desventajas. Aquí sólo hablaremos de los principales.

  • Si usa diferir en un archivo JS principal, probablemente no verá sus efectos de 'iniciador' hasta que se instale.
  • Si usa demasiado aplazar, puede causar un cuello de botella en la CPU al final de la carga de la página.

Desde que se escribió este artículo, se lanzó la actualización de Chrome 80. En la columna Iniciador, ahora es mucho más fácil ver qué recurso llama qué recurso. Por ejemplo, puede ver una imagen o un archivo CSS llamado por JS. Si se desplaza por los recursos manteniendo presionada la tecla Mayús, también verá qué recurso no se puede usar sin cargar otros recursos.

Desplazarse mientras se mantiene presionada la tecla Mayús: el color rojo indica el recurso condicional para el recurso resaltado en verde.

También puede usar la nueva sección Iniciador de Chrome para obtener un orden de carga de recursos, un iniciador y una revisión de prioridad más detallados. Esto le permite detectar cadenas de llamadas JS extremadamente largas y costosas como la siguiente.

Un ejemplo de una cadena de llamadas JS larga y costosa desde el mismo sitio. Sobre el recurso seleccionado están sus iniciadores. La siguiente parte muestra los recursos iniciados por el recurso seleccionado.

  • Los archivos JS diferidos se descargan después del evento domInteractive, por lo que debe elegirlos de acuerdo con sus archivos e imágenes CSS.
  • Si aplaza algunos archivos JS de terceros del rastreador de usuarios, es posible que no pueda rastrear ciertos comportamientos de los usuarios.
  • Defer generalmente no bloquea el proceso DOM, pero Async sí lo hace. El navegador descarga los archivos JS con atributos asíncronos durante el análisis de HTML y el procesamiento de CSSOM.
  • Si usa demasiado el atributo asíncrono, probablemente creará un cuello de botella en el procesamiento de la CPU y también ralentizará sus procesos DOM y CSSOM. Debe elegir cuidadosamente qué diferir o sincronizar.

Aquí hay un esquema de ejemplo para atributos asíncronos y diferidos. El primero se carga antes que domContentLoaded sin dividir el análisis de HTML durante la obtención. En el segundo, el archivo JS obtenido no se ejecuta antes de que finalice el análisis de HTML.

Sugerencias y consejos para la representación y el rendimiento de Javascript

Antes de entrar en ejemplos prácticos, aquí hay algunas sugerencias para mejorar el rendimiento de la representación de JavaScript. Esto también podría ayudar a proporcionar una mejor comprensión de la velocidad de la página y cómo funciona un navegador.

No utilice variables innecesarias.

Si es SEO, puede notar variables innecesarias o no utilizadas en un archivo JavaScript. Hay muchas herramientas que se pueden utilizar para detectar este tipo de error. A continuación encontrará dos ejemplos básicos de variables no utilizadas e innecesarias.

var carName= marca+ ” ” + año;
document.getElementById(“demo”).innerHTML = carName;

Aquí, la variable "carName" es innecesaria. Puedes sugerir la siguiente modificación:
document.getElementById(“demo”).innerHTML = marca+ ” ” + año

O:

[a, b, c, d, e].forEach(función (valor, índice) {
consola.log(índice);
});

Aquí, el parámetro "valor" no es necesario, porque no se utiliza. Puedes eliminarlo:
[a, b, c, d, e].forEach(función (índice) {
consola.log(índice);
});

En el lado derecho, puede ver tiempos de conexión más largos (líneas blancas) y los archivos CSS y JS se cargan en orden asimétrico gracias a los Javascripts "asincrónicos".

En el lado izquierdo, los tiempos de conexión son más cortos y los archivos CSS y JS no se mezclan porque cada fuente se carga en filas. Los atributos asíncronos pueden reducir su índice de velocidad, ya que pueden extender el tiempo de TBT, por lo que debe realizar una investigación e informarla a su equipo de desarrolladores para los archivos JS del rastreador de rendimiento desde la pestaña de rendimiento, o puede realizar algunos experimentos usted mismo.

Usar herramientas para tareas difíciles

Para un principiante en código, encontrar variables innecesarias o no utilizadas puede ser difícil. Es posible que desee utilizar algunas herramientas para estas tareas, como Chrome DevTools o paquetes Node.js como Unused (Kami/node-unused: un módulo que informa variables definidas, pero no utilizadas en su código, o para más variables no utilizadas). Si encuentra incluso algunos errores pequeños, creo que su equipo de TI lo escuchará para mejorar sus archivos JavaScript.

Uso del Informe de cobertura de Chrome DevTools para encontrar código JavaScript no utilizado

El informe de cobertura de Chrome DevTools muestra fragmentos de código JavaScript no utilizados, pero no es muy práctico. Puede pensar que puede eliminar todas las partes rojas del código, pero no es el caso... En su lugar, debe encontrar funciones o variables completamente sin usar para un gran número de páginas de categorías. De esta manera, se puede convencer a su equipo de desarrolladores para que utilice un proceso TreeShaking.

TreeShaking significa eliminar el código muerto de los archivos. Recomiendo aprender a usar variables JS no utilizadas y paquetes de búsqueda de funciones para ganar tiempo.

Un tamaño de DOM más pequeño también ayudará con la representación de JavaScript. Cada comando (getElementsByTagName) escaneará su DOM. Un tamaño de DOM más pequeño requerirá menos recursos de su navegador y de la CPU/red de su dispositivo al renderizar JavaScript.

Con la nueva actualización de Chrome 80, el informe de cobertura también sufrió un cambio. Han agregado opciones opcionales por función y por bloque. Por bloque es el valor predeterminado aquí.

Si elige Por función, verá una gran diferencia en su informe. La razón principal de esta situación es que la vista Por función comprueba si se está utilizando toda la función o no. Si se utiliza el 95 % de la función, la opción Por función lo definirá como código no utilizado porque no se utiliza el 5 % del código, aunque se utiliza la mayor parte de la función.

Comprime, Minimiza o Uglifica tus archivos JS.

Esto se puede hacer de dos formas. Primero, elimine los espacios y comentarios innecesarios. En segundo lugar, use operadores de JavaScript mejorados para sus archivos JS y manipule nombres, variables y funciones con tecnologías listas para usar.

Debe conocer las funciones de flecha para este tipo de compresión. Por ejemplo, en lugar de este ejemplo de 84 caracteres:

función flecha Islev (a, b) {
consola.log (a + b);
}
flechaFonksiyon (5, 6);

Puede comprimirlo a solo 50 caracteres con funciones de flecha =>
constante ab = (a, b) => b + a;
consola.log (ab (5, 6));

Otro método de acortar/comprimir es válido para declaraciones If. En lugar de este fragmento de código con 63 caracteres:
si (a<b) {
consola.log(ab);
}
demás {
consola.log(a+b);

Puedes usar el que tiene 43 caracteres a continuación:
(a<b) ? consola.log(ab) : consola.log(a+b);

También puede sugerirle a su equipo de TI que use los signos $ y _ para la compresión. La mayoría de los archivos JavaScript funcionan para reinterpretar DOM. Para esto, puede ver muchos document.getElementById(x); fragmentos de código en archivos. Puede usar un signo $ para esta tarea. Esto lo salvará de una enorme pila de tamaño inútil.

La mayoría de las bibliotecas de JavaScript usan $ de forma predeterminada para la definición de funciones, pero no todas, porque $ también es un carácter alfabético.

En esta situación, puede sugerir que su equipo de TI use:
función $(x) {return document.getElementById(x);} .

Usar un tipo de renderizado apropiado

JavaScript y tipos de representación de páginas web en términos de compatibilidad con SEO.
SSR Hydration significa que algunos de los componentes de JS se renderizarán utilizando Client Side Rendering. Es útil para FP y FMP, pero puede haber algunas desventajas para TTI y Speed ​​Index Scores.
Fuente de la imagen: Notprovided.eu

Prácticas recomendadas de codificación para el rendimiento de representación de JavaScript

  • Otra importante contribución a la compresión vendrá del uso de “_”. Puede usar "guión bajo.js" para mejorar los formatos y funciones de escritura de JavaScript. De esta forma, creará archivos JS más pequeños mientras manipula listas y colecciones con funciones JS más cortas sin funciones JS integradas.
  • El uso de muchos cambios de variables largos y agotadores y la contaminación de variables globales también son fuentes de renderizado lento. Debe determinar las opciones generales de alcance de sus funciones y los tipos de variable global/variable larga. Usar variables locales con 'Let' es mejor para renderizar. Debido a las variables locales, los navegadores no auditarán otras variables de funciones globales para el próximo cambio.

Para simular un examen de rendimiento más realista, por ejemplo, lo que podría ver en teléfonos móviles de gama baja, debe utilizar las preferencias de aceleración de la CPU y conexión 3G rápida/lenta en Chrome DevTools.
Fuente de la imagen: Addy Osmani

  • El uso de funciones JS más pequeñas y cadenas de variables ayudará a su rendimiento de representación. Además, es mejor usar el selector "este" en lugar del selector "con". El selector "Este" en Javascript es un código de funcionamiento local a diferencia de "con", la misma lógica con let y var también es válida aquí.
  • Si usa sus declaraciones en fragmentos de código de bucle For, esto también ralentizará un poco la velocidad de representación. Porque su declaración de función iterará a través de cada elemento del bucle. Simplemente puede crear una nueva variable para los elementos del bucle y puede llamar a estos elementos con una función que esté fuera del bucle For.
  • Si desea llegar a un elemento HTML varias veces, puede crear una variable para él y llamarlo con las funciones que desee. Llegar a un elemento HTML con JavaScript no es un proceso rápido. Simplemente puede crear más de una carga para su navegador.

Otra forma de mejorar el rendimiento de la representación de Javascript es la representación trisomórfica a través de Service Workers. Puede colocar algunos de sus archivos JS en la memoria del navegador del cliente para futuras sesiones. De esta manera, puede hacer que su sitio web funcione sin conexión.
Puede encontrar una demostración simple para una mejor comprensión y la oportunidad de practicar con los trabajadores de servicio aquí

Atarlo: cómo la optimización de JavaScript y la velocidad de la página afecta al SEO

Para evitar que los activos de JavaScript saboteen la velocidad de su página, hemos visto cómo Defer y Async pueden marcar una gran diferencia. También analizamos algunas de las estrategias de "depuración" y sugerencias de codificación que pueden ayudarlo a mejorar la velocidad de sus páginas con recursos de JavaScript.

Ahora que hemos visto cómo los navegadores crean páginas web, cómo se mide y afecta la velocidad de la página, y el papel que desempeña la optimización de JavaScript en el tiempo de carga de la página, el siguiente artículo demostrará cómo el orden de carga de los recursos afecta la velocidad de la página y el presupuesto de rastreo.

Si está interesado en revisar los artículos anteriores de esta serie de cuatro artículos, puede encontrarlos aquí:

  • “¿Cómo crea un navegador una página web?”
  • “Métricas Avanzadas de Velocidad de Página”.
Comienza tu prueba gratuita