Tamanhos grandes do DOM têm um efeito maior na interatividade do que você imagina. Neste guia, explicamos o motivo e o que você pode fazer.
Não há como evitar: quando você cria uma página da Web, ela tem um Modelo de objeto de documento (DOM). O DOM representa a estrutura do HTML da página e dá ao JavaScript e ao CSS acesso à estrutura e ao conteúdo de uma página.
No entanto, o problema é que o tamanho do DOM afeta a capacidade de um navegador renderizar uma página com rapidez e eficiência. Em geral, quanto maior o DOM, mais caro é 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 interações que modificam ou atualizam o DOM acionam um trabalho de layout caro que afeta a capacidade de resposta rápida da página. O trabalho de layout caro pode afetar a Interação com a próxima renderização (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 apenas o necessário.
Quando o DOM de uma página é muito grande?
De acordo com o Lighthouse, o tamanho do DOM de uma página é excessivo quando excede 1.400 nós. O Lighthouse vai começar a emitir avisos quando o DOM de uma página exceder 800 nós. Confira este exemplo de HTML:
<ul>
<li>List item one.</li>
<li>List item two.</li>
<li>List item three.</li>
</ul>
No código acima, há quatro elementos do DOM: o elemento <ul>
e os três elementos filhos <li>
. Sua página da Web quase certamente terá muito mais nós do que isso. Por isso, é importante entender o que você pode fazer para manter os tamanhos do DOM sob controle, além de outras estratégias para otimizar o trabalho de renderização depois que o DOM de uma página estiver o menor possível.
Como DOMs grandes afetam a performance da página?
DOMs grandes afetam a performance da página de algumas maneiras:
- Durante a renderização inicial da página. Quando o CSS é aplicado a uma página, uma estrutura semelhante ao DOM, conhecida como Modelo de objeto CSS (CSSOM), é criada. À medida que os seletores de CSS aumentam em especificidade, o CSSOM se torna mais complexo, e mais tempo é necessário para executar o layout, o estilo, a composição e o trabalho de pintura necessários para desenhar a página da Web na tela. Esse trabalho extra aumenta a latência de interação para interações que ocorrem no início do carregamento da página.
- Quando as interações modificam o DOM, seja por inserção ou exclusão de elementos, ou modificando o conteúdo e os estilos do DOM, o trabalho necessário para renderizar essa atualização pode resultar em um layout, estilização, composição e pintura muito caros. Assim como no render inicial da página, um aumento na especificidade do seletor de CSS pode adicionar trabalho de renderização quando elementos HTML são inseridos no DOM como resultado de uma interação.
- Quando o JavaScript consulta o DOM, as referências aos 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 de memória poderá ser considerável se o resultado retornar um grande número de elementos DOM.
Todos esses fatores podem afetar a interatividade, mas o segundo item da lista acima é de importância especial. Se uma interação resultar em uma mudança no DOM, ela poderá iniciar muito trabalho que pode contribuir para um INP ruim em uma página.
Como faço para medir o tamanho do DOM?
É possível medir o tamanho do DOM de algumas maneiras. O primeiro método usa o Lighthouse. Ao executar uma auditoria, as estatísticas sobre o DOM da página atual vão estar na auditoria "Evite um tamanho excessivo do DOM", no cabeçalho "Diagnóstico". Nesta seção, você pode conferir o número total de elementos DOM, o elemento DOM que contém mais elementos filhos e o elemento DOM mais profundo.
Um método mais simples envolve o uso do console JavaScript nas ferramentas para desenvolvedores em qualquer navegador principal. Para saber o número total de elementos HTML no DOM, use o seguinte código no console depois que a página for carregada:
document.querySelectorAll('*').length;
Se quiser ver a atualização do tamanho do DOM em tempo real, use a ferramenta de monitoramento de desempenho. Com essa ferramenta, é possível correlacionar operações de layout e estilização (e outros aspectos de desempenho) com o tamanho atual do DOM.
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 do usuário e, assim, melhorar o INP do seu site.
Como posso medir o número de elementos do DOM afetados por uma interação?
Se você estiver criando um perfil de uma interação lenta no laboratório que suspeita ter algo a ver com o tamanho do DOM da página, selecione qualquer atividade no criador de perfil rotulada como "Recalcular estilo" e observe os dados contextuais no painel inferior para descobrir quantos elementos do DOM foram afetados.
Na captura de tela acima, observe que o recálculo de estilo do trabalho (quando selecionado) 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 em uma página com muitos elementos DOM, essas informações de diagnóstico são úteis em qualquer caso para determinar se o tamanho do DOM é um fator limitante no tempo necessário para a exibição do próximo frame em resposta a uma interação.
Como posso reduzir o tamanho do DOM?
Além de auditar o HTML do seu site para encontrar marcações desnecessárias, a principal maneira de reduzir o tamanho do DOM é diminuir a profundidade dele. Um sinal de que seu DOM pode estar desnecessariamente profundo é se você estiver vendo uma marcação parecida com esta na guia Elementos das ferramentas para desenvolvedores do navegador:
<div>
<div>
<div>
<div>
<!-- Contents -->
</div>
</div>
</div>
</div>
Quando você vê padrões como esse, provavelmente é possível simplificá-los ao reduzir a estrutura do DOM. Isso reduz o número de elementos DOM e provavelmente oferece uma oportunidade de simplificar os estilos da página.
A profundidade do DOM também pode ser um sintoma dos frameworks que você usa. Em particular, frameworks baseados em componentes, como aqueles que dependem de JSX, exigem que você aninhe vários componentes em um contêiner principal.
No entanto, muitos frameworks permitem evitar o aninhamento de componentes usando o que é conhecido como fragmentos. Os frameworks baseados em componentes que oferecem fragmentos como um recurso incluem (mas não se limitam a):
Ao usar fragmentos no framework de sua escolha, é possível reduzir a profundidade do DOM. Se você estiver preocupado com o impacto que o nivelamento da estrutura do DOM tem no estilo, use modos de layout mais modernos (e rápidos), como flexbox ou grid.
Outras estratégias a serem consideradas
Mesmo que você se esforce para reduzir a árvore DOM e remover elementos HTML desnecessários para manter o DOM o menor possível, ele ainda pode ser muito grande e iniciar muito trabalho de renderização à medida que muda em resposta às interações do usuário. Se você estiver nessa situação, há outras estratégias que podem ser consideradas para limitar o trabalho de renderização.
Considere uma abordagem aditiva
É possível que grandes partes da sua página não estejam visíveis para o usuário quando ela é renderizada pela primeira vez. Essa pode ser uma oportunidade de carregar o HTML de forma lenta, omitindo essas partes do DOM na inicialização, mas adicionando-as quando o usuário interage com as partes da página que exigem os aspectos inicialmente ocultos.
Essa abordagem é útil durante o carregamento inicial e talvez até depois. Para o carregamento inicial da página, você assume menos trabalho de renderização antecipadamente, o que significa que o payload HTML inicial será mais leve e será renderizado mais rapidamente. Isso vai dar às interações durante esse período crucial mais oportunidades de serem executadas com menos concorrência pela atenção da linha de execução principal.
Se você tiver muitas partes da página que ficam ocultas inicialmente no carregamento, isso também poderá acelerar outras interações que acionam o trabalho de renderização. No entanto, à medida que outras interações adicionam mais ao DOM, o trabalho de renderização aumenta conforme 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 próprias compensações. Se você estiver seguindo esse caminho, provavelmente estará fazendo solicitações de rede para receber dados e preencher o HTML que pretende adicionar à página em resposta a uma interação do usuário. Embora as solicitações de rede em andamento não sejam contabilizadas para o INP, elas podem 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 os seletores no seu CSS, ele precisa percorrer a árvore 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 realizar a renderização inicial da página, bem como o aumento dos recálculos de estilo e do trabalho de layout se a página mudar como resultado de uma interação.
Usar a propriedade content-visibility
O CSS oferece a propriedade content-visibility
, que é uma maneira de renderizar elementos DOM fora da tela de forma lenta. À 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 eliminam uma quantidade significativa de trabalho de renderização na renderização inicial da página, mas também ignoram o trabalho de renderização de elementos fora da tela quando o DOM da página é alterado como resultado de uma interação do usuário.
Conclusão
Reduzir o tamanho do DOM para apenas o que é estritamente necessário é uma boa maneira de otimizar o INP do seu site. Assim, você reduz o tempo necessário para o navegador realizar o trabalho de layout e renderização quando o DOM é atualizado. Mesmo que não seja possível reduzir significativamente o tamanho do DOM, há algumas técnicas que podem ser usadas para isolar o trabalho de renderização em uma subárvore do DOM, como o isolamento de CSS e a propriedade content-visibility
do CSS.
De qualquer forma, criar um ambiente em que o trabalho de renderização seja minimizado, além de reduzir a quantidade de trabalho de renderização que sua página faz em resposta às interações, vai resultar em um site mais responsivo para os usuários quando eles interagirem com ele. Isso significa que você terá um INP menor no seu site, o que se traduz em uma experiência do usuário melhor.