Escrito por Ramón SaSquet
com A passagem dos usuários de dispositivos de desktop para dispositivos móveis, a otimização das páginas da Web no cliente torna-se mais interesse do que no passado, equivale a importância às otimizações no servidor. E é para fazer uma rodada rápida em dispositivos que são mais lentos e com conexões que, dependendo da cobertura, podem ser ruins ou mesmo cortes, não é uma tarefa fácil, mas é necessário, uma vez que eles têm uma velocidade mais alta envolverá usuários mais satisfeitos que nos visitarão com mais frequência e melhor posicionamento nas pesquisas do celular.
Neste artigo Vou tentar alguns dos pontos em que você tem que prestar mais atenção no momento da otimização do JavaScript que é executado no cliente. Primeiro de tudo, vamos ver como otimizar seu download e compilação e, em segundo lugar, como otimizar sua execução para que a página tenha um bom desempenho. Compreender para o desempenho, a definição dada pelo modelo do Google Rail. Esses acrônimos significam:
- resposta de interface em menos de 100 ms.
- animações com a plena desenhada a cada 16ms que são 60 fps ou 60 imagens por segundo.
- desativado: quando o usuário não interage com a página o que é executado em segundo plano, ele não deve durar mais de 50ms.
- carga: a página deve carregar em 1000ms.
Estes tempos, devemos alcançá-los no pior caso (quando a web é executada em um celular antigo), com poucos processadores e recursos de memória.
Em seguida, primeiro, as ações necessárias para otimizar a descarga e compilação e, em segundo lugar, as ações necessárias para otimizar a execução do código, sendo essa parte mais técnica, mas não menos importante.
Ações para otimizar o download e compilação do código JavaScript
Cachear no navegador
Aqui temos duas opções. A primeira é usar a API de cache de API JavaScript, a partir da qual podemos usar instalando um trabalhador de serviço. A segunda é usar o cache do protocolo HTTP. Se usarmos a API de cache, nosso aplicativo poderia ter a opção de operar no modo desconectado. Se usarmos o cache de protocolo HTTP, aproximadamente, devemos configurá-lo usando o parâmetro de controle de cache com valores de idade pública e máxima, com um grande tempo de cache, como um ano. Depois, se quisermos invalidar esse cache, alteraremos o nome para o arquivo.
Compress com Brotli Q11 e GZIP
Ao compactar o código JavaScript, estamos reduzindo os bits que são transmitidos pela rede e, portanto, o tempo de transmissão, mas deve-se ter em mente que estamos aumentando o tempo de processamento no servidor e no cliente, já que o primeiro deve compactar o arquivo e o segundo descomprimido. Podemos salvar a primeira vez se tivermos um cache de arquivos compactados no servidor, mas o tempo de descompressão no cliente mais o tempo de transmissão compactado, pode ser maior que o tempo de transmissão do arquivo descompactado, fazendo essa técnica download mais lento. Isso acontecerá apenas com arquivos muito pequenos e com altas velocidades de transmissão. A velocidade de transmissão do usuário não pode saber, mas pode ser dito ao nosso servidor que não compreende os arquivos muito pequenos, por exemplo, informando que ele não compreende os arquivos menores que 280 bytes. Em conexões com altas velocidades, acima de 100MB / s, esse valor deve ser muito maior, mas é sobre otimizar para aqueles que têm conexões móveis com pouca cobertura, onde a perda de desempenho é mais pronunciada, embora em conexões rápidas sejam um pouco mais lentas.
O novo algoritmo de compressão de Brotli melhora a compressão em relação ao gzip em 17%. Se o navegador enviar, no cabeçalho do protocolo HTTP, o valor “BR” dentro do parâmetro de codificação de acasio, isso significará que o servidor pode enviar o arquivo no formato Brotli em vez de no GZIP.
Minimizar
Consiste em usar uma ferramenta automática para eliminar comentários, espaços, guias e substituir as variáveis para tornar o código ocupar menos espaço.Os arquivos minimizados devem ser lotados no servidor ou gerado já minimizado ao carregá-los, pois se o servidor tiver que minimizá-los com cada solicitação, ele terá um desempenho negativo.
unificar o código JavaScript
Esta é uma técnica de otimização que não é muito importante se o nosso site funcionar com https e http2, uma vez que este protocolo envia os arquivos como se fossem apenas um, mas se o nosso site funcionar com http1.1 ou esperamos Tenha muitos clientes com navegadores antigos que usam este protocolo, a unificação é necessária para otimizar o download. Mas não precisam ser passados e unificar todo o código da Web no arquivo exclusivo, pois se apenas o código que você precisar do usuário em cada página for enviado, os bytes podem ser bastante reduzidos. Para fazer isso, separaremos o código base necessário para todo o portal do que será executado em cada página individual. Desta forma, teremos dois arquivos JavaScript para cada página, um com as bibliotecas básicas que serão comuns para todas as páginas e outra com o código específico da página. Com uma ferramenta como webpack, podemos unificar e minimizar esses dois grupos de arquivos em nosso projeto de desenvolvimento. Tente que a ferramenta que você use para isso gerará os chamados “Mapas de origem”. Estes são arquivos .map associados ao cabeçalho do arquivo final e na qual a relação entre o código minimizado e unificado e os arquivos de código-fonte reais são estabelecidos. Dessa forma, podemos depurar o código sem problemas.
A opção para unificar tudo em um único arquivo maior, tem o lado bom que você pode bater todo o código JavaScript na Web no navegador, em A primeira visita e, na próxima carga, o usuário não precisará baixar todo o código JavaScript. Então, essa opção eu recomendo somente se a economia de bytes é praticamente desprezível em relação à técnica anterior e temos uma baixa taxa de rebote.
Marcar o Javascript como assíncrono
Inclua o JavaScript da seguinte forma:
<script async src="/codigo.js" />
Desta forma, estamos impedindo a aparência do rótulo de script bloqueando o estágio do documento da página da página.
Não use o JavaScript incorporado na página
Ao usar a tag de script para incorporar código na página, a construção DOM também é bloqueada e ainda mais se a função Document.write for usada () . Em outras palavras, isso é proibido:
< script > document.write (“Olá mundo!”) < / script >
Carregue o javascript no cabeçalho da página com async
Antes de ter a tag Async, foi recomendado colocar todas as tags de script na parte inferior da página para evitar bloquear a construção dele. Isso não é mais necessário, na verdade é melhor que esteja dentro da etiqueta <, de modo que o JavaScript começa a baixar, analisar e compilar o mais rápido possível, uma vez que essas fases são os que mais acontecem. Se este atributo não for usado, o javascript deve estar no final.
excluir javascript que não é usado
Neste ponto, não estamos apenas reduzindo o tempo de transmissão, mas também o Tempo que leva você ao navegador analisar e compilar o código. Para isso, devemos levar em conta os seguintes pontos:
- Se for detectado que uma funcionalidade não está sendo usada pelos usuários, podemos excluí-la com todo o seu código JavaScript associado, para que o A Web cobrará mais rápido e os usuários vão apreciá-lo.
- Também podemos ser incluídos por enganhar Alguma biblioteca que não é necessária ou temos bibliotecas que oferecem alguma funcionalidade a partir da qual já temos nativamente em todos os navegadores, sem necessidade Para usar o código adicional e mais rapidamente.
- Finalmente, se quisermos otimizar o fim, independentemente do tempo que você usar, devemos eliminar o código que não estamos usando dentro das bibliotecas. Mas eu não recomendo, porque nunca sabemos quando você pode precisar ser necessário.
Postpone a carga javascript que não é necessária:
deve ser feito com essas funcionalidades que não são necessárias para a inicial desenhada da página. Eles são funcionalidades para as quais o usuário deve executar uma determinada ação para executá-lo. Desta forma, evitamos carregar e compilando o código JavaScript que atrasaria a visualização inicial. Depois que a página estiver totalmente carregada, podemos iniciar a carga dessas funcionalidades para que elas estejam imediatamente disponíveis quando o usuário inicia a interação.O Google no modelo ferroviário recomenda que essa carga adiada seja feita em blocos de 50ms para que ele não influencie a interação do usuário com a página. Se o usuário interage com uma funcionalidade que ainda não tenha sido carregada, devemos cobrar nesse momento.
Ações para otimizar a execução do código JavaScript
Evite usar muita memória
Você não pode dizer quanta memória será demais, mas você pode dizer que devemos sempre tentar não usar mais do que o necessário, porque não sabemos quanta memória terá o dispositivo que executará a teia. Quando o coletor de lixo do navegador é executado, é para a execução do JavaScript, e isso acontece toda vez que nosso código solicita que o navegador reserve uma nova memória. Se isso acontecer com freqüência, a página será executada lentamente.
Na guia “Memória” das ferramentas do desenvolvedor do Chrome, podemos ver a memória ocupada por cada função JavaScript:
Evite vazamentos de memória
Se tivermos um vazamento de memória em um loop, a página estará reservando mais e mais memória ocupando todo o dispositivo disponível e tornar tudo cada vez mais lento. Essa falha é geralmente dada em carrosséis e controles deslizantes de imagens.
No Chrome Podemos analisar se o nosso site tiver vazamentos de memória com a gravação de uma linha do tempo na guia Desempenho das ferramentas do desenvolvedor:
geralmente vazamentos de memória vêm por peças de SDU que são eliminadas da página, mas que eles têm Qualquer variável que os faça referência e, portanto, o coletor de lixo não possa eliminá-los e não entender como o escopo das variáveis e fechamentos no trabalho JavaScript.
EUA Trabalhadores da Web quando você precisa executar o código Você precisa de um tempo de execução
Todos os processadores hoje são multi-células e multi-core, mas JavaScript tem sido tradicionalmente uma linguagem monohilous e, embora tenha temporizadores, estes são executados no mesmo tópico de execução, no qual, Além disso, a interação com a interface é executada, portanto, enquanto o JavaScript está executando a interface é bloqueada e leva mais de 50ms será perceptível. Trabalhadores da Web e Trabalhadores de Serviços nos trazem a execução multi-ventilador para JavaScript, embora não permitam acesso direto ao domingo, então teremos que pensar como atrasar o acesso a este, a fim de aplicar trabalhadores da Web em casos que tem um código que a tarde mais de 50ms a ser executada.
Usando a API do FETCH (AJAX)
O uso da API Buscar ou Ajax também é uma boa maneira para o usuário perceba um tempo de carga mais rápido, mas não devemos usá-lo na carga inicial, mas na navegação subseqüente e de uma forma indexável. Para isso, a melhor maneira de implementar é usar uma estrutura que usa JavaScript universal.
prioriza o acesso a variáveis locais
javascript primeiro veja se a variável existe locally e segue a descoberta Nas áreas superiores, sendo as últimas variáveis globais. JavaScript accede más rápido a variables locales porque no tiene que buscar la variable en ambitos superiores para encontrarla, así que es una buena estrategia guardar en variables locales aquellas variables de un ámbito superior a las que vamos a acceder varias veces y, además, no crear nuevos ámbitos con clausuras o con las sentencias with y try catch, sin que sea necesario.
Si accedes varias veces a un elemento del DOM guárdalo en una variable local
El acceso al DOM é lento. Então, se vamos ler o conteúdo de um item várias vezes, salve-o melhor em uma variável local, então o JavaScript não terá que procurar o elemento ao sol toda vez que quiser acessar seu conteúdo. Mas preste atenção, se você mantiver uma peça de Dom em uma variável que você remova mais tarde da página e não usará mais, tente, então, atribuir para “null” a variável onde você a salvou para não causar vazamento de memória .
grupo e minimizar leituras e scripts DOM e CSSOM
de
quando o navegador desenha uma página executa o caminho de representação crítica que segue as seguintes etapas na primeira carga:
- O HTML é recebido.
- começa a construir o DOM.
- Enquanto o DOM é construído, os recursos externos são solicitados (CSS e JS).
- o CCSOM (Dom mistura e o CSS) é construído.
- A árvore de representação é criada (elas são as partes do CSSOM que serão desenhadas).
- A partir da árvore de representação é calculada a geometria de cada parte visível da árvore em uma camada. Este estágio é chamado de layout ou refluxo.
- Na fase final da pintura, as camadas da etapa 6 são pintadas e estão compondo um em cima do outro para mostrar a página para o usuário.
- Se você terminou de compilar o JavaScript, ele é executado (na verdade, este passo pode ocorrer em qualquer ponto depois do passo 3, sendo melhor o mais rápido possível).
- Se na etapa anterior, o código JavaScript force Para refazer parte do DOM ou o CSSOM Retornamos vários passos atrás que será executado até ponto 7.
Embora os navegadores estejam colando as alterações do Árvore de representação e decidir quando fazer a repintura, se tivermos um loop em que lemos o DOM e / ou o CSSOM e modificá-lo na próxima linha, o navegador pode ver f Estado para executar o refluxo ou repintura a página várias vezes, especialmente se a seguinte leitura depender da escrita anterior. É por isso que é recomendado:
- Separe todas as leituras em um loop separado e faça todos os escritos de uma só vez com a propriedade CSStext, se for o CSSOM ou o Innerhtml se for o Sunder, então O navegador que você só terá que lançar uma repintura.
- Se as leituras depender das escrituras anteriores, procure uma maneira de reescrever o algoritmo para que isso não seja assim.
- se Você não tem escolha aplicar muitas mudanças em um elemento do domingo, tirá-lo do domingo, faça as alterações e devolva-a para apresentar onde estava.
- No Google Chrome, podemos analisar o que acontece na rota de representação crítica com a ferramenta do farol na guia “Audits” ou na guia “Desempenho” gravando o que acontece enquanto a página é carregada.
Use a função RestostanimationFrame (retorno de chamada) em animações e os efeitos que dependem do rolo
A função RestostAnimationFrame (), faz com que a função que seja passada como um parâmetro não cause uma repintura, até que o próximo agendado. Isso, além de evitar a repintura desnecessária, tem o efeito de que as animações parem enquanto o usuário estiver em outra guia, economizando a bateria de CPU e dispositivo.
Os efeitos que dependem do rolo são mais lentos, porque o seguinte Dom Propriedades Forçam um refluxo (etapa 7 do ponto anterior) ao acessá-los:
offsetTop, offsetLeft, offsetWidth, offsetHeightscrollTop, scrollLeft, scrollWidth, scrollHeightclientTop, clientLeft, clientWidth, clientHeightgetComputedStyle() (currentStyle en IE)
Se além de acessar uma dessas propriedades, então com base neles, Nós pinamos um banner ou um menu que o seguem movendo o rolo ou um efeito de rolagem, várias camadas repintando toda vez que você move o rolo, afetando negativamente o tempo de resposta da interface, com a qual podemos ter um rolo que está dando saltos de deslizar suavemente. Portanto, com esses efeitos, a última posição do rolo no evento Onscroll deve ser salva em uma variável global e depois de usar a função RestostanimationFrame () somente se a animação anterior terminar.
Se houver Muitos eventos similares Agric It
Se você tiver 300 botões que, quando você clicar em fazer praticamente o mesmo, podemos atribuir um evento ao elemento pai dos botões 300 em vez de atribuir 300 eventos a cada um deles. Ao clicar em um botão, o evento “Bubble” para o pai e, a partir disso, podemos saber qual é o botão que o usuário clicou e modificou o comportamento de acordo.
Cuidado com os eventos que atiram várias vezes seguidos
Eventos como onMousemove ou onscroll, atire várias vezes seguidas enquanto a ação é executada. Portanto, tente controlar que o código associado não funciona mais vezes do que os necessários, já que este é um erro bastante comum.
Evite a execução de código com código com eval (), função (), settimeout () e setinterval ()
o fato de introduzir código em um literal a ser analisado e compilado Durante a execução do restante do código é bastante lento, por exemplo: Eval (“C = A + B”); Você pode sempre refazer o programa para evitar ter que fazer isso.
Implementar as otimizações que você aplicaria em qualquer outra linguagem de programação
- sempre usar os algoritmos com a menor complexidade computacional o complexidade ciclomática para a tarefa a ser resolvida.
- usa as estruturas de dados ideais para atingir o ponto anterior.
- Reescreva o algoritmo para obter o mesmo resultado com menos cálculos.
- Evite chamadas recursivas, alterando o algoritmo por um equivalente que faz uso de uma pilha.
- Faça uma função com um alto custo e chamadas repetidas ao longo de diferentes blocos de código economizando na memória Próxima chamada.
- Coloque os cálculos e chamadas para funções repetidas nas variáveis.
- Quando você anda um loop, armazene o tamanho do loop em uma variável primeiro, para evitar o calculá-lo novamente , em sua condição de conclusão, em cada iteração.
- Factorizar e simplifica fórmulas matemáticas.
- substitui cálculos que não dependem de variáveis por constantes e deixam o cálculo comentado.
- usa matrizes de pesquisa: eles servem para obter um valor baseado em outro de usar um bloco de mudança.
- Faça as condições sempre mais propensas a aproveitar a execução especulativa do processador, uma vez que a previsão de saltos falhará menos.
- simplificar expressões booleanas Com as regras da lógica booleana ou melhor ainda com os mapas de Karnaugh.
- usa operadores no nível de bits quando você pode usá-los para substituir determinadas operações, uma vez que esses operadores usam menos ciclos de processador. Usá-los requer que a aritmética binária sabe, por exemplo: ser valor XA de uma variável inteira, podemos colocar “y = x > > 1 ; ” em vez de “y = x / 2;” ou “y = x & 0xff;” Em vez de “y = x% 256”.
Estes são alguns dos meus favoritos, sendo os mais importantes os três primeiros e os mais estudos e práticos exigem. Os últimos são micro-otimizações que só valem a pena se você realizar enquanto você escreve o código ou se é algo computável muito caro como um editor de vídeo ou um videogame, embora nesses casos você seja melhor que a WebAssembly em vez de JavaScript .
Ferramentas para detectar problemas
já vimos vários. De todos eles, o farol é o mais fácil de interpretar, já que simplesmente nos dá uma série de pontos para melhorar, como também pode nos dar os insights do Google PagePeed ou, muitos outros, como gtmetrix. No Chrome, também podemos usar, na opção “Mais ferramentas” no menu principal, o Gerenciador de Tarefas, para ver a memória e a CPU usada por cada guia. Para análise ainda mais técnica, temos as ferramentas para desenvolvedores do Firefox e Google Chrome, onde temos a guia chamada “Desempenho” e que nos permite analisar os tempos de cada fase, vazamentos de memória, etc. Vamos ver um exemplo:
Todas as informações que vemos acima podem ser gravadas enquanto a página é carregado, nós administramos uma ação ou fazemos pergaminho. Em seguida, podemos ampliar uma parte do gráfico para vê-lo em detalhes e, se, como neste caso, o que mais é a execução do JavaScript, podemos implantar a seção principal e clicar em cima dos scripts que demoram mais . Assim, a ferramenta nos mostrará em detalhes na guia de baixo para cima, pois ele está afetando o JavaScript a cada fase do caminho de representação crítica e na guia Resumo, ele indicará com um aviso se detectado um problema de desempenho em JavaScript. Clutish na parte superior do arquivo que indica, ele nos levará especificamente à linha que produz o atraso.
Finalmente, para análise ainda mais fina, é aconselhável usar a API de temporização de navegação de JavaScript que nos permite medir esta parte de cada parte do nosso código do Programação em si.
Recomendações finais
Como você vê, a otimização do JavaScript não é uma tarefa fácil e carrega um processo de análise e otimização de mão-de-obra que pode facilmente exceder o orçamento destinado ao desenvolvimento que tínhamos inicialmente pensou. Portanto, há poucos sites, plugins e tópicos mais famosos para os gerentes de conteúdo habituais que apresentam muitos dos problemas que listei.
Se o seu site apresentar esses problemas, tente resolver aqueles que maior impacto tiverem o desempenho e buscar sempre que as otimizações não afetam a capacidade de manutenção e qualidade do código. É por isso que não recomendo o uso de técnicas de otimização mais extremas, como a remoção de chamadas para funções, substituindo-as pelo código que chamam, o desenrolamento de loops ou o uso da mesma variável para tudo, para que tenha sido Cache ou dos registros do processador, uma vez que são técnicas que sujas o código e, na compilação no Javascript Runtime, algumas delas são aplicadas. Então, lembre-se:
O desempenho não é um requisito que nunca deve estar acima da facilidade de detectar erros e adicionar funcionalidades.
Entre em contato conosco se quiser ajudá-lo a melhorar sua visibilidade online. Conte-nos sobre o que seu projeto está indo e apresentaremos uma proposta personalizada para as necessidades do seu negócio.