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

Los tamaños grandes de DOM tienen más efecto en la interactividad de lo que crees. En esta guía, se explica por qué y qué puedes hacer.

No hay forma de evitarlo: cuando compilas una página web, esa página tendrá un modelo de objetos del documento (DOM). El DOM representa la estructura del código HTML de tu página y les brinda a JavaScript y CSS acceso a la estructura y el contenido de una página.

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

Esto se vuelve problemático en las páginas con DOM muy grandes cuando las interacciones que modifican o actualizan el DOM activan un trabajo de diseño costoso que afecta la capacidad de la página para responder con rapidez. El trabajo de diseño costoso puede afectar la interacción de una página con la siguiente pintura (INP). Si deseas que una página responda rápidamente a las interacciones del usuario, es importante que te asegures de que los tamaños del DOM sean lo suficientemente grandes como sea necesario.

¿Cuándo el DOM de una página es 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 supere los 800 nodos. Por ejemplo, considera 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 DOM: el elemento <ul> y sus tres elementos secundarios <li>. Es casi seguro que tu página web tenga muchos más nodos que este, por lo que es importante comprender qué puedes hacer para controlar los tamaños del DOM, así como otras estrategias para optimizar el trabajo de renderización una vez que hayas reducido el DOM de una página lo más posible.

¿Cómo afectan los DOM grandes el rendimiento de la página?

Los DOM grandes afectan el rendimiento de la página de las siguientes 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 de CSS aumentan en especificidad, el CSSOM se vuelve más complejo y se necesita más tiempo para ejecutar el diseño, el estilo, la composición y el trabajo de pintura necesarios para dibujar la página web en la pantalla. Este trabajo adicional aumenta la latencia de interacción para las interacciones que se producen al principio de la carga de la página.
  2. Cuando las interacciones modifican el DOM, ya sea a través de la inserción o eliminación de elementos, o bien mediante la modificación del contenido y los estilos del DOM, el trabajo necesario para renderizar esa actualización puede generar un trabajo de diseño, aplicación de estilos, composición y pintura muy costoso. Al igual que en el caso de la renderización inicial de la página, un aumento en la especificidad del selector CSS puede aumentar el 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 DOM.
Captura de pantalla de una tarea larga causada por un trabajo de renderización excesivo en el panel de rendimiento de Chrome DevTools. La pila de llamadas de la tarea larga muestra un tiempo significativo dedicado a volver a calcular los estilos de página, así como la pintura previa.
Una tarea larga, como se muestra en el generador de perfiles de rendimiento de las Herramientas para desarrolladores de Chrome. La tarea larga que se muestra se debe a la inserción de elementos DOM en un DOM grande a través de JavaScript.

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

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

Puedes medir el tamaño del DOM de varias maneras. El primer método usa Lighthouse. Cuando ejecutes una auditoría, las estadísticas sobre el DOM de la página actual se encontrará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 DOM, el elemento DOM que contiene la mayor cantidad de elementos secundarios y el elemento DOM más profundo.

Un método más sencillo consiste en usar la consola de JavaScript en las herramientas para desarrolladores de cualquier navegador importante. Para obtener la cantidad total de elementos HTML en el DOM, puedes usar el siguiente código en la consola después de que se cargue 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 del rendimiento. Con esta herramienta, puedes correlacionar las operaciones de diseño y diseño de componentes (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, se muestran varios aspectos del rendimiento de la página que se pueden supervisar de forma continua durante su ciclo de vida. En la captura de pantalla, se supervisa de forma activa la cantidad de nodos DOM, los diseños por segundo y los cálculos nuevos de estilo por sección.
El monitor de rendimiento en las Herramientas para desarrolladores de Chrome. En esta vista, la cantidad actual de nodos DOM de la página se grafica junto con las operaciones de diseño y los cálculos nuevos de estilo que se realizan 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 descubrir cómo reducir el tamaño del DOM para mejorar la capacidad de tu página de responder a las interacciones del usuario, de modo 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 estás generando perfiles de una interacción lenta en el lab que sospechas que podría tener algo que ver con el tamaño del DOM de la página, puedes averiguar cuántos elementos del DOM se vieron afectados seleccionando cualquier actividad en el generador de perfiles etiquetada como "Recalculate Style" y observando los datos contextuales en el panel inferior.

Captura de pantalla de la actividad de recálculo de diseño seleccionada en el panel de rendimiento de Chrome DevTools. En la parte superior, el segmento de interacciones muestra una interacción de clic, y la mayor parte del trabajo se dedica a volver a calcular el estilo y a realizar el trabajo previo a la pintura. En la parte inferior, un panel muestra más detalles de la actividad seleccionada, que informa que se vieron afectados 2,547 elementos del DOM.
Observa la cantidad de elementos afectados en el DOM como resultado del trabajo de recá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 que fue superior a 200 milisegundos, que es el umbral designado como "bueno" para la INP.

En la captura de pantalla anterior, observa que, cuando se selecciona el rediseño del estilo del trabajo, se muestra la cantidad de elementos afectados. Si bien la captura de pantalla anterior 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 cualquier caso para determinar si el tamaño del DOM es un factor limitante en el 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 en busca de marcas innecesarias, la forma principal de reducir el tamaño del DOM es reducir su profundidad. Un indicador de que tu DOM podría ser innecesariamente profundo es si ves un marcado que se ve de la siguiente manera 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 aplanando la estructura del DOM. De esta manera, se reducirá la cantidad de elementos del DOM y es probable que te brinde la oportunidad de simplificar los estilos de la 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 dependen de JSX, requieren que anides varios componentes en un contenedor superior.

Sin embargo, muchos frameworks te permiten evitar anidar componentes con lo que se conocen como fragmentos. Entre los frameworks basados en componentes que ofrecen fragmentos como una función, se incluyen los siguientes:

Si usas fragmentos en el framework que elijas, puedes reducir la profundidad del DOM. Si te preocupa el impacto que tiene el aplanamiento de la estructura del DOM en el diseño, te recomendamos que uses modos de diseño más modernos (y más rápidos), como flexbox o grid.

Otras estrategias que debes considerar

Incluso si te esfuerzas por aplanar el árbol del DOM y quitar los elementos HTML innecesarios para mantener el DOM lo más pequeño posible, puede ser bastante grande y generar mucho trabajo de renderización a medida que cambia en respuesta a las interacciones del usuario. Si te encuentras en esta situació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 situación en la que el usuario no pueda ver grandes partes de tu página inicialmente cuando se renderiza por primera vez. Esta podría ser una oportunidad para cargar HTML de forma diferida omitiendo esas partes del DOM en el inicio, pero agregándolas cuando el usuario interactúe con las partes de la página que requieren los aspectos ocultos inicialmente.

Este enfoque es útil durante la carga inicial y, quizás, incluso después. Para la carga inicial de la página, realizarás menos trabajo de renderización de antemano, lo que significa que tu carga útil HTML inicial será más liviana y se renderizará más rápido. Esto les dará a las interacciones durante ese período crucial más oportunidades de ejecutarse con menos competencia por la atención del subproceso principal.

Si tienes muchas partes de la página que están ocultas inicialmente durante la carga, también podría acelerar otras interacciones que activan el trabajo de renderización. Sin embargo, a medida que otras interacciones agregan más elementos 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 elementos al DOM con el tiempo puede ser complicado y tiene sus propias compensaciones. Si eliges esta opción, es probable que realices solicitudes de red para obtener datos que propaguen el código HTML que deseas agregar a la página en respuesta a una interacción del usuario. Si bien las solicitudes de red en curso no se registran en la INP, pueden aumentar la latencia percibida. Si es posible, muestra un ícono giratorio de carga o algún otro indicador que muestre que se están recuperando datos para que los usuarios comprendan que está sucediendo algo.

Limita la complejidad del selector CSS

Cuando el navegador analiza los selectores en tu CSS, debe recorrer el árbol del DOM para comprender cómo (y si) se aplican esos selectores al diseño actual. Cuanto más complejos sean estos selectores, más trabajo tendrá que hacer el navegador para realizar la renderización inicial de la página, así como un mayor trabajo de recálculo de estilo y 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 eficaz de renderizar de forma diferida elementos del DOM fuera de la pantalla. A medida que los elementos se acercan al viewport, se renderizan a pedido. Los beneficios de content-visibility no solo eliminan una cantidad significativa de trabajo de renderización en la renderización inicial de la página, sino que también omiten el trabajo de renderización de los elementos fuera de la pantalla cuando se cambia el DOM de la página como resultado de una interacción del usuario.

Conclusión

Reducir el tamaño del DOM a solo lo que es estrictamente necesario es una buena manera de optimizar el INP de tu sitio web. De esta manera, puedes reducir la cantidad de 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, hay 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 CSS content-visibility.

Sin embargo, crear un entorno en el que se minimice el trabajo de renderización, además de reducir la cantidad de trabajo de renderización que realiza tu página en respuesta a las interacciones, hará que tu sitio web se sienta más responsivo para los usuarios cuando interactúen con él. Esto significa que tendrás un INP más bajo para tu sitio web, lo que se traduce en una mejor experiencia del usuario.