Como tamanhos grandes de DOM afetam a interatividade e o que você pode fazer a respeito

Os DOMs grandes têm um efeito maior na interatividade do que você imagina. Este guia explica os motivos e o que você pode fazer.

Não há como evitar: quando você cria uma página da Web, ela vai ter um Modelo de objeto de documentos (DOM, na sigla em inglês). O DOM representa a estrutura do HTML da página e concede acesso a JavaScript e CSS à estrutura e ao conteúdo da página.

No entanto, o problema é que o tamanho do DOM afeta a capacidade do navegador de renderizar uma página de maneira rápida e eficiente. De modo geral, quanto maior for o DOM, mais caro será para renderizar inicialmente essa página e atualizar a renderização mais tarde no ciclo de vida da página.

Isso se torna problemático em páginas com DOMs muito grandes, quando as interações que modificam ou atualizam o DOM acionam um layout caro que afeta a capacidade da página de responder rapidamente. Trabalhos de layout caros podem afetar a Interaction to Next Paint (INP) de uma página. Se você quiser que uma página responda rapidamente às interações do usuário, é importante garantir que os tamanhos do DOM sejam grandes somente o necessário.

Quando o DOM de uma página é muito grande?

De acordo com o Lighthouse (link em inglês), o tamanho do DOM de uma página é excessivo quando ultrapassa 1.400 nós. O Lighthouse começará a emitir avisos quando o DOM de uma página exceder 800 nós. Veja o seguinte HTML, por exemplo:

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

No código acima, há quatro elementos DOM: o elemento <ul> e os três elementos filhos <li>. É quase certo que sua página da Web tenha muito mais nós do que isso. Por isso, é importante entender o que você pode fazer para manter os tamanhos do DOM sob controle, bem como outras estratégias para otimizar o trabalho de renderização quando o DOM de uma página for o menor possível.

Como DOMs grandes afetam o desempenho da página?

DOMs grandes afetam o desempenho da página de algumas maneiras:

  1. Durante a renderização inicial da página. Quando o CSS é aplicado a uma página, é criada uma estrutura semelhante ao DOM conhecida como Modelo de objetos CSS (CSSOM, na sigla em inglês). Conforme os seletores de CSS aumentam em especificidade, o CSSOM se torna mais complexo e é necessário mais tempo para executar o layout, estilo, composição e trabalho de pintura necessários para desenhar a página da Web na tela. Esse trabalho a mais aumenta a latência de interação para interações que ocorrem no início, durante o carregamento da página.
  2. Quando as interações modificam o DOM, seja pela inserção ou exclusão de elementos, seja pela modificação de conteúdos e estilos do DOM, o trabalho necessário para renderizar essa atualização pode resultar em alto custo de layout, estilo, composição e pintura. Como acontece com a renderização inicial da página, um aumento na especificidade do seletor de CSS pode aumentar o trabalho de renderização quando elementos HTML são inseridos no DOM como resultado de uma interação.
  3. Quando o JavaScript consulta o DOM, as referências a elementos DOM são armazenadas na memória. Por exemplo, se você chamar document.querySelectorAll para selecionar todos os elementos <div> em uma página, o custo da memória poderá ser considerável se o resultado retornar um grande número de elementos DOM.
.
Captura de tela de uma tarefa longa causada por trabalho excessivo de renderização no painel de desempenho do Chrome DevTools. A pilha de chamadas da tarefa longa mostra um tempo significativo gasto no recálculo de estilos de página e na pré-pintura.
Uma tarefa longa, como mostrado no Performance Profiler do Chrome DevTools. A tarefa longa mostrada é causada pela inserção de elementos DOM em um DOM grande via JavaScript.

Todos esses fatores podem afetar a interatividade, mas o segundo item na lista acima é de especial importância. Se uma interação resultar em uma alteração no DOM, ela poderá iniciar um grande trabalho que pode contribuir para um INP insatisfatório em uma página.

Como medir o tamanho do DOM?

Você pode medir o tamanho do DOM de duas maneiras. O primeiro método usa o Lighthouse. Quando você executa uma auditoria, as estatísticas do DOM da página atual são exibidas na coluna "Evitar um tamanho excessivo do DOM". em "Diagnóstico" Nesta seção, você pode ver o número total de elementos DOM, o elemento DOM que contém mais elementos filhos, bem como o elemento DOM mais profundo.

Um método mais simples envolve o uso do Console JavaScript nas ferramentas para desenvolvedores de qualquer navegador principal. Para obter o número total de elementos HTML no DOM, use o seguinte código no console após o carregamento da página:

document.querySelectorAll('*').length;

Para conferir a atualização do tamanho do DOM em tempo real, use a ferramenta de monitoramento de desempenho. Com essa ferramenta, você pode correlacionar operações de layout e estilo (e outros aspectos de desempenho) com o tamanho atual do DOM.

Uma captura de tela do monitor de desempenho no Chrome DevTools. À esquerda, há vários aspectos do desempenho da página que podem ser monitorados continuamente durante a vida útil da página. Na captura de tela, o número de nós DOM, layouts por segundo e recálculos de estilo por seção está sendo monitorado ativamente.
O monitor de desempenho no Chrome DevTools. Nessa visualização, o número atual de nós DOM da página é mostrado no gráfico com as operações de layout e recálculos de estilo realizados por segundo.

Se o tamanho do DOM estiver se aproximando do limite de aviso do Lighthouse ou falhar completamente, a próxima etapa será descobrir como reduzir o tamanho do DOM para melhorar a capacidade da página de responder às interações dos usuários e melhorar o INP do site.

Como posso medir o número de elementos DOM afetados por uma interação?

Se você estiver criando um perfil de interação lenta no laboratório e suspeite que ela esteja relacionada ao tamanho do DOM da página, poderá descobrir quantos elementos do DOM foram afetados selecionando qualquer parte da atividade no criador de perfil chamada "Recalcular estilo". e observe os dados contextuais no painel inferior.

Uma captura de tela da atividade de recálculo de estilo selecionada no painel de desempenho do Chrome DevTools. No topo, a faixa de interações mostra uma interação de clique, e a maior parte do trabalho é gasto com recálculos de estilo e pré-pintura. Na parte inferior, há um painel com mais detalhes sobre a atividade selecionada, que informa que 2.547 elementos DOM foram afetados.
Observar o número de elementos afetados no DOM como resultado do trabalho de recálculo de estilo. A parte sombreada da interação na faixa de interações representa a parte da duração da interação que foi superior a 200 milissegundos, que é a designação "boa" limite para INP.

Na captura de tela acima, o recálculo de estilo do trabalho mostra o número de elementos afetados. Embora a captura de tela acima mostre um caso extremo do efeito do tamanho do DOM no trabalho de renderização de uma página com muitos elementos DOM, essa informação de diagnóstico é útil de qualquer forma para determinar se o tamanho do DOM é um fator limitante de quanto tempo leva para o próximo frame ser exibido em resposta a uma interação.

Como posso reduzir o tamanho do DOM?

Além de auditar o HTML de seu site para marcações desnecessárias, a principal forma de reduzir o tamanho do DOM é reduzir a profundidade dele. Um sinal de que seu DOM pode estar desnecessariamente profundo é se você estiver vendo uma marcação com esta aparência na guia Elementos das ferramentas para desenvolvedores do seu navegador:

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

Ao observar padrões como esse, você provavelmente pode simplificá-los nivelando sua estrutura DOM. Isso reduzirá o número de elementos DOM e provavelmente dará a você uma oportunidade de simplificar os estilos das páginas.

A profundidade do DOM também pode ser um sintoma das estruturas usadas. Em particular, frameworks baseados em componentes, como aqueles que dependem de JSX, exigem que você aninhe vários componentes em um contêiner pai.

No entanto, muitos frameworks permitem evitar o aninhamento de componentes usando o que são conhecidos como fragmentos. Estruturas baseadas em componentes que oferecem fragmentos como um recurso incluem, sem limitação:

Ao usar fragmentos no framework de sua escolha, você pode reduzir a profundidade do DOM. Se você estiver preocupado com o impacto do achatamento da estrutura DOM sobre o estilo, pode se beneficiar do uso de modos de layout mais modernos (e mais rápidos), como flexbox ou grid.

Outras estratégias a considerar

Mesmo que você se esforce para nivelar sua árvore do DOM e remover elementos HTML desnecessários para mantê-lo o menor possível, ela ainda pode ser muito grande e iniciar um grande trabalho de renderização à medida que muda em resposta às interações do usuário. Se você estiver nessa posição, há algumas outras estratégias que pode considerar para limitar o trabalho de renderização.

Considere uma abordagem aditiva

É possível que você esteja em uma posição em que grande parte da página não esteja inicialmente visível para o usuário na primeira renderização. Essa pode ser uma oportunidade para fazer o carregamento lento do HTML omitindo essas partes do DOM na inicialização e adicionando-as quando o usuário interagir com as partes da página que exigem os aspectos inicialmente ocultos.

Essa abordagem é útil durante o carregamento inicial e talvez até mesmo depois. Para o carregamento da página inicial, você assumirá menos trabalho de renderização antecipadamente, o que significa que sua carga HTML inicial será mais leve e mais rápida. Isso dará às interações durante esse período crucial mais oportunidades de correr com menos concorrência pela atenção da linha de execução principal.

Se você tem muitas partes da página que estão inicialmente ocultas no carregamento, isso também pode acelerar outras interações que acionam o trabalho de nova renderização. No entanto, à medida que outras interações acrescentam mais elementos ao DOM, o trabalho de renderização aumenta à medida que o DOM cresce ao longo do ciclo de vida da página.

Adicionar ao DOM ao longo do tempo pode ser complicado e tem suas desvantagens. Se seguir esse caminho, você provavelmente estará fazendo solicitações de rede para obter dados a fim de preencher o HTML que pretende adicionar à página em resposta a uma interação do usuário. Embora as solicitações de rede em trânsito não sejam contabilizadas para o INP, isso pode aumentar a latência percebida. Se possível, mostre um ícone de carregamento ou outro indicador de que os dados estão sendo buscados para que os usuários entendam que algo está acontecendo.

Limitar a complexidade do seletor de CSS

Quando o navegador analisa seletores no CSS, ele precisa atravessar a árvore do DOM para entender como e se esses seletores se aplicam ao layout atual. Quanto mais complexos forem esses seletores, mais trabalho o navegador terá para executar a renderização inicial da página, bem como recálculos de estilo maiores e trabalho de layout, se a página for alterada como resultado de uma interação.

Usar a propriedade content-visibility

O CSS oferece a propriedade content-visibility, que é uma maneira eficaz de renderizar lentamente elementos DOM fora da tela. À medida que os elementos se aproximam da janela de visualização, eles são renderizados sob demanda. Os benefícios do content-visibility não apenas reduzem uma quantidade significativa de trabalho de renderização na renderização inicial da página, mas também pulam o trabalho de renderização de elementos fora da tela quando o DOM da página é modificado como resultado de uma interação do usuário.

Conclusão

Reduzir o tamanho do DOM apenas ao que é estritamente necessário é uma boa maneira de otimizar o INP do seu site. Ao fazer isso, você pode reduzir o tempo que o navegador leva para executar o trabalho de layout e renderização quando o DOM é atualizado. Mesmo que não seja possível reduzir significativamente o tamanho do DOM, existem algumas técnicas que podem ser usadas para isolar o trabalho de renderização em uma subárvore do DOM, como a contenção de CSS e a propriedade CSS content-visibility.

Independentemente do método, criando um ambiente em que o trabalho de renderização seja minimizado, bem como reduzindo o trabalho de renderização que a página realiza em resposta às interações, o resultado será um site mais responsivo aos usuários. Isso significa que o INP do seu site será menor, o que resulta em uma melhor experiência do usuário.

Imagem principal do Unsplash, de Louis Reed.