Otimizando recursos JavaScript para velocidade de página

Publicados: 2020-05-05

O exemplo abaixo é de um site de notícias grande e complexo. Eles vêm perdendo tráfego orgânico há anos. O tempo do evento DOMContentLoaded é 2615,2 MS. Você pode pensar que o tamanho do DOM deles é extremamente grande, mas não…

É quase o mesmo que o Google recomenda, e apenas 1230 nós HTML existem neste documento.

Você pode calcular o tempo e o processo do seu evento domContentLoaded e compará-lo com seus concorrentes usando o DevTools.

Examinar este exemplo mostra que o tamanho do DOM não é necessariamente o ponto crítico. Aqui, o principal problema é Resource Order : as partes azuis em “Main Tab” são para análise de HTML. No entanto, este site interrompe o navegador com a renderização de JavaScript antes que o processo de análise de HTML seja concluído.

(Você também pode usar a seção Árvore de chamadas para ajudar a encontrar erros semelhantes para sua equipe de TI.)

Este exemplo ilustra claramente a importância de otimizar os ativos JavaScript e o que pode dar errado quando você negligencia o JavaScript em suas otimizações de velocidade de página.

Este é o terceiro de uma série de quatro artigos. Para entender melhor este artigo, você pode querer ler os dois primeiros artigos da série:

  • A renderização de Javascript e a velocidade da página estão intimamente relacionadas a como o mecanismo de renderização de um navegador cria uma página da web.
  • Você também deve entender as métricas avançadas de velocidade da página antes de entrar neste artigo.

Vou usar alguns exemplos dos dois primeiros artigos para ajudar a contextualizar neste.

O que é renderização de Javascript e como isso está afetando a velocidade da sua página?

A renderização de Javascript é a seção de carregamento da última página que pode alterar interativamente a estrutura criada usando o DOM e o CSSOM. Qualquer elemento de página pode ser alterado em um formato acionável pelo usuário ou exibido normalmente. Qualquer elemento com uma propriedade display:none que não possa ser acessado pela árvore de renderização pode ser tornado visível com JavaScript ou injetado por meio de diferentes elementos HTML no DOM.

O JavaScript interrompe o DOM e o CSSOM porque altera o DOM e o CSSOM no momento em que são lidos pelo navegador. Portanto, para evitar que isso afete negativamente o tempo e a velocidade de carregamento da página, é necessário examinar a relação entre a renderização do DOM, CSSOM e JavaScript.

Acima está um exemplo de uma árvore de renderização. Todos os trechos de código interligados nos nós CSSOM e HTML têm equivalentes semânticos na árvore de renderização. Se você observar com atenção, notará que o nó HTML “Botão de Ação” não está na árvore de renderização. A principal razão para isso é “display:none;” propriedade CSS. Devido a esse comando de invisibilidade, ele não é incluído na árvore de renderização. Para ver como os elementos desta árvore foram construídos, você pode querer ler o primeiro artigo desta série.

Se você tiver muitos elementos de página que não aparecerão no primeiro carregamento porque dependem do comportamento do usuário, na ordem de carregamento do recurso, você terá que separar esses itens e colocá-los na última linha. Usar um shadow DOM ou um virtual DOM são as melhores opções neste momento.

Adiar e atributos assíncronos para recursos JavaScript

Se você colocar seus arquivos JS na seção e se você não usar os atributos 'defer' ou 'async', provavelmente atrasará seu tempo de DOMContentLoaded. Para evitar essa situação, podemos usar esses dois atributos. Adiar é atrasar o processo de carregamento de um arquivo JS enquanto 'Async' é carregar JS e outras fontes de maneira paralela. Ambos têm vantagens e desvantagens. Aqui falaremos apenas dos principais.

  • Se você usar defer em um arquivo JS principal, provavelmente não verá seus efeitos de 'iniciador' até que ele seja instalado.
  • Se você usar adiar demais, poderá causar um gargalo de CPU no final do carregamento da página.

Desde que este artigo foi escrito, a atualização do Chrome 80 foi lançada. Na coluna Iniciador, agora é muito mais fácil ver qual recurso é chamado por qual recurso. Por exemplo, você pode ver uma imagem ou arquivo CSS chamado por JS. Se você rolar pelos recursos mantendo pressionada a tecla shift, também verá qual recurso não pode ser usado sem carregar outros recursos.

Rolagem mantendo pressionada a tecla shift: a cor vermelha indica o recurso condicional para o recurso destacado em verde.

Você também pode usar a nova seção Iniciador do Chrome para obter uma ordem de carregamento de recursos mais detalhada, um iniciador e uma revisão de prioridade. Isso permite detectar cadeias de chamadas JS extremamente longas e caras, como a abaixo.

Um exemplo de uma cadeia de chamadas JS longa e cara do mesmo site. Acima do recurso selecionado estão seus iniciadores. A próxima parte mostra os recursos iniciados pelo recurso selecionado.

  • Os arquivos JS adiados são baixados após o evento domInteractive, portanto, você precisa escolhê-los de acordo com seus arquivos e imagens CSS.
  • Se você adiar alguns arquivos JS de terceiros do rastreador de usuários, talvez não consiga rastrear determinados comportamentos do usuário.
  • Defer geralmente não bloqueia o processo DOM, mas o Async sim. Arquivos JS com atributos assíncronos são baixados pelo navegador durante a análise de HTML e o processamento de CSSOM.
  • Se você usar muito o atributo assíncrono, provavelmente criará um gargalo de processamento da CPU e também diminuirá a velocidade de seus processos DOM e CSSOM. Você precisa escolher cuidadosamente o que deve ser adiado ou assíncrono.

Aqui está um esquema de exemplo para atributos assíncronos e adiados. O primeiro é carregado antes do domContentLoaded sem dividir a análise de HTML durante a busca. No segundo, o arquivo JS obtido não é executado antes que a análise de HTML seja concluída.

Sugestões e dicas para renderização e desempenho de Javascript

Antes de entrar em exemplos práticos, aqui estão algumas sugestões para melhorar o desempenho de renderização de JavaScript. Isso também pode ajudar a fornecer uma melhor compreensão da velocidade da página e de como um navegador funciona.

Não use variáveis ​​desnecessárias.

Se você é SEO, pode notar variáveis ​​desnecessárias ou não utilizadas em um arquivo JavaScript. Existem muitas ferramentas que podem ser usadas para detectar esse tipo de erro. Você encontrará dois exemplos básicos para variáveis ​​não utilizadas e desnecessárias abaixo.

var carName= marca+ ” ” + ano;
document.getElementById(“demo”).innerHTML = carName;

Aqui, a variável “carName” é desnecessária. Você pode sugerir a seguinte modificação:
document.getElementById(“demo”).innerHTML = marca+ ” ” + ano

Ou:

[a, b, c, d, e].forEach(função (valor, índice) {
console.log(índice);
});

Aqui, o parâmetro “valor” não é necessário, pois não é utilizado. Você pode removê-lo:
[a, b, c, d, e].forEach(função (índice) {
console.log(índice);
});

No lado direito, você pode ver tempos de conexão mais longos (linhas brancas) e arquivos CSS e JS são carregados em ordem assimétrica graças a Javascripts “assíncronos”.

No lado esquerdo, os tempos de conexão são menores e os arquivos CSS e JS não são misturados porque cada fonte é carregada em linhas. Os atributos assíncronos podem reduzir seu Índice de velocidade, pois podem estender o tempo de TBT, portanto, você precisa realizar uma investigação e relatá-la à sua equipe de desenvolvedores para arquivos JS do rastreador de desempenho na guia de desempenho ou pode executar alguns experimentos sozinho.

Use ferramentas para tarefas difíceis

Para um iniciante em código, encontrar variáveis ​​desnecessárias ou não utilizadas pode ser difícil. Você pode querer usar algumas ferramentas para essas tarefas, como Chrome DevTools ou pacotes Node.js como Unused (Kami/node-unused: um módulo que relata variáveis ​​definidas, mas não utilizadas em seu código ou para mais variáveis ​​não utilizadas). Se você encontrar alguns pequenos erros, acredito que sua equipe de TI ouvirá você para melhorar seus arquivos JavaScript.

Como usar o relatório de cobertura do Chrome DevTools para encontrar código JavaScript não utilizado

O relatório de cobertura do Chrome DevTools mostra trechos de código JavaScript não utilizados, mas não é muito prático. Você pode pensar que pode deletar todas as partes vermelhas do código, mas não é o caso... Em vez disso, você deve encontrar funções ou variáveis ​​completamente não utilizadas para um grande número de páginas de categorias. Dessa forma, sua equipe de desenvolvedores pode ser convencida a usar um processo de TreeShaking.

TreeShaking significa deletar código morto de arquivos. Eu recomendo aprender usando variáveis ​​JS não utilizadas e pacotes de busca de funções para ganhar tempo.

Um tamanho menor do DOM também ajudará na renderização do JavaScript. Cada comando (getElementsByTagName) verificará seu DOM. Um tamanho menor do DOM exigirá menos recursos do seu navegador e da CPU/rede do seu dispositivo ao renderizar o JavaScript.

Com a nova atualização do Chrome 80, o relatório de cobertura também passou por uma mudança. Eles adicionaram opções opcionais por função e por bloco. Por bloco é o valor padrão aqui.

Se você escolher Por Função, verá uma grande diferença em seu relatório. A principal razão para esta situação é que a visualização Por Função verifica se toda a função está sendo usada ou não. Se 95% da função estiver sendo usada, a opção Por Função a definirá como código não utilizado porque 5% do código não é usado, embora a maior parte da função seja usada.

Comprima, minifique ou uglifique seus arquivos JS.

Isso pode ser feito de duas maneiras. Primeiro, exclua os espaços e comentários desnecessários. Segundo, use operadores JavaScript aprimorados para seus arquivos JS e mangle nomes, variáveis, funções com tecnologias prontas para uso.

Você deve conhecer as funções de seta para esse tipo de compactação. Por exemplo, em vez deste exemplo de 84 caracteres:

função seta Islev (a, b) {
console.log (a + b);
}
arrowFonksiyon (5, 6);

Você pode compactá-lo para apenas 50 caracteres com funções de seta =>
const ab = (a, b) => b + a;
console.log (ab (5, 6));

Outro método encurtar/comprimir é válido para instruções If. Em vez deste trecho de código com 63 caracteres:
se (a<b){
console.log(ab);
}
senão {
console.log(a+b);

Você pode usar aquele com 43 caracteres abaixo:
(a<b) ? console.log(ab) : console.log(a+b);

Você também pode sugerir à sua equipe de TI que eles usem os sinais $ e _ para compactação. A maioria dos arquivos JavaScript funciona para reinterpretar o DOM. Para isso, você pode ver muitos document.getElementById(x); trechos de código em arquivos. Você pode usar um sinal $ para esta tarefa. Isso irá salvá-lo de uma enorme pilha de tamanho inútil.

A maioria das bibliotecas JavaScript usa $ por padrão para definição de funções, mas não todas, porque $ também é um caractere alfabético.

Nessa situação, você pode sugerir que sua equipe de TI use:
function $(x) {return document.getElementById(x);} .

Use um tipo de renderização apropriado

JavaScript e tipos de renderização de páginas da web em termos de compatibilidade com SEO.
Hidratação SSR significa que alguns dos componentes JS serão renderizados usando a renderização do lado do cliente. É útil para FP e FMP, mas pode haver algumas desvantagens para TTI e pontuações de índice de velocidade.
Fonte da imagem: Notprovided.eu

Práticas recomendadas de codificação para desempenho de renderização de JavaScript

  • Outra importante contribuição de compressão virá do uso de “_”. Você pode usar “underscore.js” para formatos e funções de escrita JavaScript aprimorados. Dessa forma, você criará arquivos JS menores enquanto manipula listas e coleções com funções JS mais curtas sem funções JS integradas.
  • Usar muitas mudanças de variáveis ​​longas e exaustivas e poluição de variáveis ​​globais também são fontes de renderização lenta. Você deve determinar as opções gerais de escopo de suas funções e os tipos de variável global/variável longa. Usar variáveis ​​locais com 'Let' é melhor para renderização. Por causa das variáveis ​​locais, os navegadores não auditarão outras variáveis ​​de funções globais para a próxima alteração.

Para simular um exame de desempenho mais realista, por exemplo, o que você pode ver em telefones celulares de baixo custo, você deve usar as preferências CPU Throttling e Fast/Slow 3G Connection no Chrome DevTools.
Fonte da imagem: Addy Osmani

  • O uso de funções JS menores e cadeias de variáveis ​​ajudará seu desempenho de renderização. Além disso, usar o seletor “this” em vez do seletor “with” é melhor. O seletor “This” em Javascript é um código de funcionamento local ao contrário de “with”, a mesma lógica com let e var também é válida aqui.
  • Se você usar suas instruções em trechos de código de loop For, isso também diminuirá um pouco a velocidade de renderização. Porque sua instrução de função irá iterar através de cada elemento do loop. Você pode simplesmente criar uma nova variável para elementos de loop e pode chamar esses elementos com uma função que está fora do loop For.
  • Se você quiser acessar um elemento HTML várias vezes, você pode criar uma variável para ele e pode chamá-lo com as funções que desejar. Alcançar um elemento HTML com JavaScript não é um processo rápido. Você pode simplesmente criar mais um fardo para o seu navegador.

Outra maneira de melhorar o desempenho de renderização de Javascript é a renderização trisomórfica via Service Workers. Você pode colocar alguns de seus arquivos JS na memória do navegador do cliente para sessões futuras. Dessa forma, você pode fazer seu site funcionar offline.
Você pode encontrar uma demonstração simples para melhor compreensão e uma chance de praticar com os service workers aqui

Amarrando: como otimizar o JavaScript e a velocidade da página afeta o SEO

Para evitar que os ativos JavaScript sabotem a velocidade da sua página, vimos como Defer e Async podem fazer uma grande diferença. Também analisamos algumas das estratégias de "depuração" e dicas de codificação que podem ajudar você a melhorar a velocidade de suas páginas com recursos JavaScript.

Agora que vimos como os navegadores criam páginas da Web, como a velocidade da página é medida e afetada e o papel que a otimização do JavaScript desempenha no tempo de carregamento da página, o próximo artigo demonstrará como a ordem de carregamento dos recursos afeta a velocidade da página e o orçamento de rastreamento.

Se você estiver interessado em revisar os artigos anteriores desta série de quatro artigos, você pode encontrá-los aqui:

  • “Como um navegador cria uma página da web”
  • “Métricas avançadas de velocidade de página”.
Inicie o seu teste gratuito