El DOM (Document Object Model) es una interfaz de programación para los documentos HTML y XML y el nombre que recibe la estructura de un documento HTML, compuesto por ramas y nodos que contienen objetos.
La historia del Modelo de Objetos del Documento se remonta a la llamada "guerra de navegadores" de finales de los 90 entre Netscape Navigator y Microsoft Internet Explorer, así como con la de JavaScript y JScript, los primeros lenguajes de scripting que se implementaron ampliamente en los motores JavaScript de los navegadores web.
Estructura del DOM en WordPress: árbol, ramas y nodos
El DOM en WordPress no es muy diferente al de cualquier otra web.
<html> <-- Árbol (nodo raíz)
│
├── <head> <-- Rama
│ ├── <title> <-- Nodo (hoja)
│ └── <meta> <-- Nodo (hoja)
│
└── <body> <-- Rama
├── <header> <-- Rama
│ └── <h1> <-- Nodo (hoja)
│
├── <div> <-- Rama
│ ├── <p> <-- Nodo (interno)
│ └── <img> <-- Nodo (hoja)
│
└── <footer> <-- Rama
└── <a> <-- Nodo (hoja)
- Árbol: La página completa es representada como un árbol con un nodo raíz (
<html>
) y sus elementos hijos. - Ramas: Cada elemento dentro de un
<div>
,<header>
,<footer>
, etc., representa una rama del árbol. - Nodos: Todos los elementos HTML, como
<p>
,<img>
, o<a>
, son nodos que cuelgan de las ramas. Estos nodos pueden ser internos (que contienen otros nodos) o externos (las "hojas" del árbol que no tienen más hijos).
Así, la densidad de las ramas dependerá del tipo y cantidad de elementos que la componen. Por ejemplo, un menú de navegación complejo en WordPress puede generar varios niveles de ramas y decenas de nodos debido a la cantidad de enlaces y submenús.
Puedes pensar en los nodos como si fueran todos los elementos HTML de una página. Cuantos más elementos tenga, normalmente, más tiempo se necesita, lo que conlleva un mayor Tiempo Total de Bloqueo (TBT).
Esto puede ser una cosa difícil de optimizar en WordPress, ya que no se puede simplemente eliminar los elementos DOM que componen la estructura de una página. Sin embargo, podemos mostrar estos elementos de forma selectiva y cargar una cadena de objetos por debajo del pliegue, reduciendo así el tamaño total del DOM.
¿Por qué reducir el tamaño del DOM?
Un árbol del DOM abultado puede ralentizar el tiempo de carga de tu sitio de varias formas aumentando el uso de memoria al provocar cálculos de estilo más largos y lentos, además de un gasto prescindible del costo de datos para los usuarios.
Estos distintos escenarios pueden ser la carga innecesaria de nodos que no son visibles cuando el usuario carga la página por primera vez, la repetición de los cálculos de posición y estilo de los nodos de forma constante y el almacenamiento de una cantidad excesiva de referencias a nodos que sobrecargan la memoria de los dispositivos de los usuarios.
Los beneficios a corto y largo plazo de optimizar la velocidad de carga de una página están ya más que explicados en mil y un artículo. Resumiendo mucho, a corto plazo evitas que el personal abandone tu página aburrido de esperar y muy probablemente pasará más tiempo en ella y visitarán más páginas reduciendo la tasa de rebote. La velocidad de carga es uno de los factores reconocidos por Google en el posicionamiento SEO y entiendo que también lo es para el resto de buscadores por lo que a largo plazo el preciado tráfico orgánico aumentará.
¿Qué provoca el aumento del tamaño DOM?
En el tamaño final del DOM influyen muchos factores como la propia plantilla, lo que añaden los diferentes plugins que uses y el tipo de contenido que añadas como bloques complejos o los nefastos "sliders" de imágenes, etc . También el código que generan determinados "Builders".
Por ejemplo, hasta 2022, año en el que abandoné Elementor porque se resistía a la optimización y era raro que no rompiera algo en casi cada actualización, sumado a un par de malas experiencias con su soporte técnico, este constructor convertía el código de la web en una auténtica sopa de letras y una pesadilla con miles de <div>. Desconozco si a día hoy ha mejorado.
En abril de ese mismo año fue cuando Elementor incorporó los Flexbox "Container" como una novedad muy novedosa y revolucionaria, cuando el contenedor ya era la base de GenerateBlocks desde hacía años.
¿Cómo medir el DOM?
Para la medición he elegido un post no muy optimizado aún, algo largo y con distintos tipos de elementos.
Empezamos por el más conocido y popular: PageSpeed Insights. Google marca allí como advertencia (en naranja) cuando el elemento body tiene más de 800 nodos y como aviso de error (en rojo) cuando el elemento body tiene más de 1.400 nodos y un mensaje con esta recomendación: "Evita un tamaño excesivo del DOM".
Dependiendo del contenido y estructura de cada página que analices encontrarás más o menos pistas de elementos a los que puedes atacar. La ventaja es que suele mostrar una imagen señalando del elemento en cuestión.
Vuelvo a recordar que todas estas alertas son sólo recomendaciones y que no hay que asustarse ni mucho menos obsesionarse con estas métricas. Hay páginas que ofrecen una correcta experiencia de usuario y una buena velocidad percibida con notas bajas en PageSpeed.
Con GTmetrix obtendremos por lo general los mismos resultados sobre el DOM.
Sin embargo, aquí su "waterfall" o gráfico de cascada de peticiones es muy útil para inspeccionar de un vistazo todos los elementos clasificados por tipos y por el tiempo que tardan en cargar.
Otras opciones similares son Pingdom o isitwp.
Pero la forma más fácil y rápida es a través de cualquier navegador. Abres la página a analizar y con botón derecho de ratón / "inspeccionar" y en la pestaña "Network" o "Red" encontrarás un waterfall mucho más detallado porque puedes completarlo haciendo scroll en la página y se irán añadiendo todas las peticiones a la lista. Después puedes ordenarlas por peso, tipo, tiempo, etc.
Bajo esta ventana encontrarás un resumen de resultados. A la izquierda el número de peticiones. A la derecha, en azul, el tiempo del evento DOMContentLoaded y en rojo el tiempo de carga de esa página.
Reducir el tamaño del DOM con "Lazy Elements" de Perfmatters
Perfmatters, ese plugin imprescindible que no me canso de recomendar, añadió en su versión 2.3.3 del 28 de agosto de 2024 una opción llamada Lazy Elements que, aunque aún está en fase Beta, funciona realmente bien para facilitar la tarea de aligerar el DOM.
Esta función permite añadir la mal llamada "carga perezosa" o "Lazy Load" a elementos específicos y sus descendientes (hijos) añadiendo cualquier porción única de una cadena de atributos (class=«ejemplo») de un contenedor padre.
También se puede añadir la clase perfmatters-lazy-element a un contenedor concreto de la plantilla o del constructor de páginas que uses.
En la documentación que proporciona Perfmatters sobre esta nueva funcionalidad se nos advierte que no se debe intentar aplicar "Lazy Load" a elementos que están por encima del pliegue. Es decir, lo que se carga en la pantalla y lo primero que ve el usuario sin desplazarse hacia abajo.
Además se apunta que, si vemos que algo se rompe visualmente, hay que asegurarse de que ha utilizado una cadena única en la página que no se comparte con otros elementos.
Al igual que con las imágenes de carga lenta, el contenido se coloca dentro de una etiqueta <noscript>
. Esto significa que todo lo que se carga de forma perezosa sigue siendo técnicamente rastreable e indexable por Google. Sin embargo, no pueden asegurar cómo tratará Google los elementos con Lazy Load en una cadena. Por lo que recomiendan, en términos de SEO, hacer pruebas primero.
Igualmente se avisa de que no se intente aplicar Lazy Load a elementos que contengan imágenes que inicien un "lightbox". Y así es, he podido comprobar que función de lightbox nativa de WordPress deja de funcionar cuando se añade en la lista la clase de un elemento que la implementa.
Por lo demás, "Lazy Elements" funciona perfectamente. Gracias a esta función he ahorrado bastante tiempo adelgazando el DOM con buenos resultados. Espero que Perfmatters siga con su desarrollo para mejorar y ampliar sus opciones.