De qué manera los tamaños grandes de DOM afectan la interactividad y qué puedes hacer al respecto

Los tamaños grandes del DOM tienen un mayor efecto en la interactividad de lo que crees. En esta guía, se explica qué puede hacer y por qué.

No hay forma de evitarlo: cuando se crea una página web, esta va a tener un Modelo de objetos del documento (DOM). El DOM representa la estructura del código HTML de tu página y permite que JavaScript y CSS accedan a la estructura y al contenido de la página.

No obstante, el problema es que el tamaño del DOM afecta la capacidad del navegador de representar una página de manera rápida y eficiente. En términos generales, cuanto más grande es un DOM, más costoso es renderizar inicialmente esa página y actualizar su renderización más adelante en su ciclo de vida.

Esto se vuelve problemático en páginas con DOM muy grandes cuando las interacciones que modifican o actualizan el DOM activan trabajos de diseño costosos que afectan la capacidad de la página para responder rápidamente. El trabajo de diseño costoso puede afectar la Interacción con el siguiente procesamiento de imagen (INP) de una página. Si quieres que una página responda rápidamente a las interacciones del usuario, es importante que te asegures de que los tamaños de tus DOM sean tan grandes como sea necesario.

¿Cuándo es el DOM de una página demasiado grande?

Según Lighthouse, el tamaño del DOM de una página es excesivo cuando supera los 1,400 nodos. Lighthouse comenzará a mostrar advertencias cuando el DOM de una página exceda los 800 nodos. Tomemos como ejemplo el siguiente código HTML:

<ul>
  <li>List item one.</li>
  <li>List item two.</li>
  <li>List item three.</li>
</ul>

En el código anterior, hay cuatro elementos del DOM: el elemento <ul> y sus tres elementos secundarios <li>. Es casi seguro que tu página web tendrá muchos más nodos que estos, por lo que es importante comprender lo que puedes hacer para controlar los tamaños del DOM, así como otras estrategias para optimizar el trabajo de renderización una vez que el DOM de una página sea lo más pequeño posible.

¿Cómo afectan los DOM grandes al rendimiento de las páginas?

Los DOM grandes afectan el rendimiento de las páginas de varias maneras:

  1. Durante la renderización inicial de la página. Cuando se aplica CSS a una página, se crea una estructura similar al DOM, conocida como CSS Object Model (CSSOM). A medida que los selectores CSS son más específicos, el CSSOM se vuelve más complejo y se necesita más tiempo para ejecutar el diseño, el estilo, la composición y la pintura necesarios para dibujar la página web en la pantalla. Este trabajo adicional aumenta la latencia de las interacciones que ocurren al principio de la carga de la página.
  2. Cuando las interacciones modifican el DOM, ya sea mediante la inserción o la eliminación de elementos, o mediante la modificación de los contenidos y estilos del DOM, el trabajo necesario para renderizar esa actualización puede resultar muy costoso de realizar diseños, estilos, composición y pintura. Al igual que con la renderización inicial de la página, un aumento en la especificidad del selector de CSS puede contribuir al trabajo de renderización cuando se insertan elementos HTML en el DOM como resultado de una interacción.
  3. Cuando JavaScript consulta el DOM, las referencias a los elementos del DOM se almacenan en la memoria. Por ejemplo, si llamas a document.querySelectorAll para seleccionar todos los elementos <div> de una página, el costo de memoria podría ser considerable si el resultado muestra una gran cantidad de elementos del DOM.
Captura de pantalla de una tarea larga causada por un exceso de trabajo de renderización en el panel de rendimiento de Herramientas para desarrolladores de Chrome. La pila de llamadas de la tarea larga muestra un tiempo significativo dedicado a volver a calcular los estilos de página, así como un procesamiento previo.
Una tarea larga, como se muestra en el generador de perfiles de rendimiento de las Herramientas para desarrolladores de Chrome. La tarea extensa que se muestra se debe a la inserción de elementos del DOM en un DOM de gran tamaño a través de JavaScript.

Todos estos elementos pueden afectar la interactividad, pero el segundo elemento de la lista anterior es de particular importancia. Si una interacción da como resultado un cambio en el DOM, puede iniciar mucho trabajo que puede contribuir a un INP deficiente en una página.

¿Cómo mido el tamaño del DOM?

Puedes medir el tamaño del DOM de dos maneras. El primer método usa Lighthouse. Cuando ejecutes una auditoría, las estadísticas del DOM de la página actual aparecerán en la auditoría "Evita un tamaño excesivo de DOM" en el encabezado "Diagnóstico". En esta sección, puedes ver la cantidad total de elementos del DOM, el elemento del DOM que contiene la mayor cantidad de elementos secundarios y el más profundo.

Un método más simple implica usar la Consola de JavaScript en las herramientas para desarrolladores en cualquier navegador principal. Para obtener el número total de elementos HTML en el DOM, puedes usar el siguiente código en la consola una vez que se haya cargado la página:

document.querySelectorAll('*').length;

Si deseas ver la actualización del tamaño del DOM en tiempo real, también puedes usar la herramienta de supervisión de rendimiento. Con esta herramienta, puedes correlacionar las operaciones de diseño y estilo (y otros aspectos de rendimiento) junto con el tamaño actual del DOM.

Captura de pantalla del monitor de rendimiento en las Herramientas para desarrolladores de Chrome. A la izquierda, existen varios aspectos del rendimiento de la página que se pueden supervisar continuamente durante el ciclo de vida de la página. En la captura de pantalla, se supervisa activamente la cantidad de nodos de DOM, diseños por segundo y recálculos de estilo por sección.
El monitor de rendimiento en las Herramientas para desarrolladores de Chrome. En esta vista, se muestra la cantidad actual de nodos de DOM de la página junto con operaciones de diseño y recálculos de estilo realizados por segundo.

Si el tamaño del DOM se acerca al umbral de advertencia del tamaño del DOM de Lighthouse o falla por completo, el siguiente paso es calcular cómo reducir el tamaño del DOM para mejorar la capacidad de tu página de responder a las interacciones del usuario de manera que pueda mejorar el INP de tu sitio web.

¿Cómo puedo medir la cantidad de elementos del DOM afectados por una interacción?

Si vas a generar perfiles de una interacción lenta en el lab que sospechas que podría estar relacionada con el tamaño del DOM de la página, puedes determinar la cantidad de elementos del DOM que se vieron afectados. Para ello, selecciona cualquier actividad en el generador de perfiles con la etiqueta "Recalculate Style" y observa los datos contextuales en el panel inferior.

Captura de pantalla de la actividad de recálculo de estilo seleccionada en el panel de rendimiento de las Herramientas para desarrolladores de Chrome. En la parte superior, el segmento de interacciones muestra una interacción de clic y la mayor parte del trabajo se dedica a recalcular el estilo y a trabajos de prepintura. En la parte inferior, hay un panel en el que se muestran más detalles de la actividad seleccionada, que informa que se vieron afectados 2,547 elementos del DOM.
Se observa la cantidad de elementos afectados en el DOM como resultado del nuevo cálculo de estilo. Ten en cuenta que la parte sombreada de la interacción en el segmento de interacciones representa la parte de la duración de la interacción superior a 200 milisegundos, que es el umbral designado como "Bueno" para INP.

En la captura de pantalla anterior, observa que el nuevo cálculo de estilo del trabajo, cuando se selecciona, muestra la cantidad de elementos afectados. Si bien en la captura de pantalla anterior se muestra un caso extremo del efecto del tamaño del DOM en el trabajo de renderización en una página con muchos elementos del DOM, esta información de diagnóstico es útil en todo caso para determinar si el tamaño del DOM es un factor limitante en cuanto al tiempo que tarda el siguiente fotograma en pintarse en respuesta a una interacción.

¿Cómo puedo reducir el tamaño del DOM?

Además de auditar el código HTML de tu sitio web para detectar lenguaje de marcado innecesario, la forma principal de reducir el tamaño del DOM es reducir la profundidad del DOM. Un indicador de que tu DOM podría ser innecesariamente profundo es si ves un lenguaje de marcado similar al siguiente en la pestaña Elementos de las herramientas para desarrolladores de tu navegador:

<div>
  <div>
    <div>
      <div>
        <!-- Contents -->
      </div>
    </div>
  </div>
</div>

Cuando veas patrones como este, probablemente puedas simplificarlos al aplanar la estructura del DOM. De esta manera, se reducirá la cantidad de elementos del DOM y probablemente tendrás la oportunidad de simplificar los estilos de página.

La profundidad del DOM también puede ser un síntoma de los frameworks que usas. En particular, los frameworks basados en componentes, como los que se basan en JSX, requieren que anides varios componentes en un contenedor superior.

Sin embargo, muchos frameworks te permiten evitar la anidación de componentes mediante el uso de lo que se conoce como fragmentos. Los frameworks basados en componentes que ofrecen fragmentos como función incluyen (entre otros) los siguientes:

Si usas fragmentos en el framework que elijas, puedes reducir la profundidad del DOM. Si te preocupa el impacto que tiene la compactación de la estructura del DOM en el diseño, puedes beneficiarte del uso de modos de diseño más modernos (y más rápidos), como flexbox o cuadrícula.

Otras estrategias para tener en cuenta

Incluso si te esfuerzas por aplanar tu árbol del DOM y quitar los elementos HTML innecesarios para que tu DOM sea lo más pequeño posible, puede ser bastante grande y dar inicio a una gran cantidad de trabajo de representación a medida que cambia en respuesta a las interacciones del usuario. Si te encuentras en esta posición, existen otras estrategias que puedes considerar para limitar el trabajo de renderización.

Considera un enfoque aditivo

Es posible que te encuentres en una posición en la que grandes partes de tu página no sean visibles inicialmente para el usuario cuando se procesa por primera vez. Esta podría ser una oportunidad para cargar HTML de forma diferida si se omiten esas partes del DOM al inicio, pero se agregan cuando el usuario interactúa con las partes de la página que requieren los aspectos inicialmente ocultos de la página.

Este enfoque es útil durante la carga inicial y, quizás, incluso después. Para la carga inicial de la página, realizas menos trabajo de renderización al principio, lo que significa que tu carga útil de HTML inicial será más ligera y se renderizará con mayor rapidez. Esto brindará a las interacciones durante ese período crucial más oportunidades de ejecutarse con menos competencia por la atención del subproceso principal.

Si muchas partes de la página permanecen ocultas durante la carga, es posible que también se aceleran otras interacciones que activan el trabajo de volver a renderizar el contenido. Sin embargo, a medida que otras interacciones agregan más al DOM, el trabajo de renderización aumentará a medida que el DOM crezca a lo largo del ciclo de vida de la página.

Agregar al DOM con el paso del tiempo puede ser complicado y tiene sus propias desventajas. Si eliges esta opción, es probable que estés realizando solicitudes de red para obtener datos y completar el código HTML que quieres agregar a la página en respuesta a una interacción del usuario. Si bien las solicitudes de red en tránsito no se cuentan para el INP, pueden aumentar la latencia percibida. Si es posible, muestra un ícono giratorio de carga o algún otro indicador de que se recuperan los datos para que los usuarios comprendan que algo está sucediendo.

Limitar la complejidad del selector de CSS

Cuando el navegador analiza selectores en tu CSS, tiene que atravesar el árbol del DOM para comprender cómo (y si) esos selectores se aplican al diseño actual. Cuanto más complejos sean estos selectores, más trabajo deberá realizar el navegador para realizar tanto la representación inicial de la página como los recálculos de estilo y el trabajo de diseño si la página cambia como resultado de una interacción.

Usa la propiedad content-visibility

CSS ofrece la propiedad content-visibility, que es una forma de renderizar de forma diferida elementos del DOM fuera de la pantalla. A medida que los elementos se acercan al viewport, se renderizan según demanda. Los beneficios de content-visibility no solo reducen una cantidad significativa de trabajo de renderización en la renderización inicial de la página, sino que también omiten el procesamiento de la renderización de elementos fuera de pantalla cuando se cambia el DOM de la página como resultado de una interacción del usuario.

Conclusión

Reducir el tamaño de tu DOM solo a lo estrictamente necesario es una buena forma de optimizar el INP de tu sitio web. De esta manera, puedes reducir el tiempo que tarda el navegador en realizar el trabajo de diseño y renderización cuando se actualiza el DOM. Incluso si no puedes reducir significativamente el tamaño del DOM, existen algunas técnicas que puedes usar para aislar el trabajo de renderización en un subárbol del DOM, como la contención de CSS y la propiedad content-visibility de CSS.

Sin importar cómo lo hagas, si creas un entorno en el que se minimice el trabajo de renderización y se reduzca la cantidad de trabajo de renderización que realiza tu página en respuesta a las interacciones, tu sitio web tendrá una mayor capacidad de respuesta para los usuarios cuando interactúen con ellos. Eso significa que tendrás un INP más bajo para tu sitio web y eso se traduce en una mejor experiencia del usuario.

Hero image de Unsplash, de Louis Reed.