Como melhorar o desempenho do seu aplicativo HTML5

Introdução

O HTML5 oferece ótimas ferramentas para melhorar a aparência visual dos aplicativos da Web. Isso é especialmente verdadeiro no âmbito das animações. No entanto, esse novo poder traz novos desafios. Na verdade, esses desafios não são tão novos e, às vezes, pode fazer sentido perguntar ao seu colega da mesa ao seu lado, o programador do Flash, como ela superou coisas semelhantes no passado.

De qualquer forma, quando se trabalha com animação, torna-se extremamente importante que os usuários percebam que essas animações são suaves. O que precisamos perceber é que a suavidade nas animações não pode ser criada simplesmente aumentando os quadros por segundo além de qualquer limite cognitivo. Infelizmente, nosso cérebro é mais inteligente do que isso. Você aprenderá que os verdadeiros 30 quadros de animação por segundo (fps) são muito melhores do que 60 fps com apenas alguns frames perdidos no meio. As pessoas odeiam irregularidades.

Este artigo tentará fornecer a você as ferramentas e as técnicas necessárias para melhorar a experiência do seu próprio aplicativo.

A estratégia

De forma alguma queremos desencorajá-lo a criar aplicativos incríveis e com visual incrível usando o HTML5.

Quando você perceber que o desempenho poderia ser um pouco melhor, volte aqui e leia sobre como é possível melhorar os elementos do seu aplicativo. Ele pode, obviamente, ajudar a fazer algumas coisas no começo, mas nunca deixe que isso prejudique sua produtividade.

Fidelidade visual++ com HTML5

Aceleração de hardware

A aceleração de hardware é um marco importante para o desempenho geral de renderização no navegador. O esquema geral é descarregar tarefas que, de outra forma, seriam calculadas pela CPU principal para a unidade de processamento gráfico (GPU) no adaptador gráfico do computador. Isso pode gerar ganhos enormes de desempenho e também reduzir o consumo de recursos em dispositivos móveis.

Esses aspectos do documento podem ser acelerados pela GPU

  • Composição de layout geral
  • Transições CSS3
  • Transformações CSS3 3D
  • Desenho em tela
  • Desenho 3D do WebGL

Embora a aceleração do canvas e WebGL sejam recursos com propósitos especiais que podem não se aplicar a seu aplicativo específico, os três primeiros aspectos podem ajudar praticamente todos os aplicativos a se tornarem mais rápidos.

O que pode ser acelerado?

A aceleração de GPU funciona pelo descarregamento de tarefas bem definidas e específicas para hardwares de finalidade especial. O esquema geral é que seu documento seja dividido em várias "camadas" que são invariantes aos aspectos da sua página que são acelerados. Essas camadas são renderizadas usando o pipeline de renderização tradicional. A GPU é usada para compor as camadas em uma única página, aplicando os "efeitos" que podem ser acelerados em tempo real. Um resultado possível é que um objeto animado na tela não precise de uma única "reformulação do layout" da página enquanto a animação acontece.

O que você precisa destacar é que você precisa facilitar a identificação do mecanismo de renderização quando ele pode aplicar a magia da aceleração de GPU. Confira o exemplo abaixo:

Embora funcione, o navegador não sabe que você está executando algo que deveria ser percebido como uma animação suave por um ser humano. Considere o que acontece quando você consegue a mesma aparência visual usando transições CSS3:

A forma como o navegador implementa essa animação está completamente oculta ao desenvolvedor. Isso, por sua vez, significa que o navegador pode aplicar truques, como a aceleração de GPU, para atingir o objetivo definido.

Há duas sinalizações de linha de comando úteis para o Chrome para ajudar a depurar a aceleração da GPU:

  1. --show-composited-layer-borders mostra uma borda vermelha ao redor dos elementos que estão sendo manipulados no nível da GPU. Bom para confirmar que suas manipulações ocorrem dentro da camada da GPU.
  2. --show-paint-rects: todas as mudanças que não são de GPU são pintadas, e isso gera uma borda clara em torno de todas as áreas repintadas. É possível ver o navegador otimizando áreas de pintura em ação.

O Safari tem sinalizações de ambiente de execução semelhantes descritas aqui.

Transições CSS3

As transições CSS tornam a animação de estilo trivial para todos, mas também são um recurso inteligente de desempenho. Como uma transição CSS é gerenciada pelo navegador, a fidelidade da animação pode ser bastante melhorada e, em muitos casos, acelerada por hardware. Atualmente, o WebKit (Chrome, Safari, iOS) tem transformações CSS aceleradas por hardware, mas está chegando rapidamente a outros navegadores e plataformas.

Você pode usar eventos transitionEnd para criar combinações poderosas, mas capturar todos os eventos finais de transição com suporte significa assistir webkitTransitionEnd transitionend oTransitionEnd.

Muitas bibliotecas já introduziram APIs de animação que utilizam transições se estiverem presentes e, caso contrário, recorrem à animação de estilo DOM padrão. scripty2, transição YUI, jQuery animate Enhanced.

Tradução CSS3

Tenho certeza de que você já anima a posição x/y de um elemento na página antes. Você provavelmente manipulou as propriedades superior e esquerda do estilo in-line. Com as transformações 2D, podemos usar a funcionalidade translate() para replicar esse comportamento.

Podemos combinar isso com a animação DOM para usar o melhor possível

<div style="position:relative; height:120px;" class="hwaccel">

  <div style="padding:5px; width:100px; height:100px; background:papayaWhip;
              position:absolute;" id="box">
  </div>
</div>

<script>
document.querySelector('#box').addEventListener('click', moveIt, false);

function moveIt(evt) {
  var elem = evt.target;

  if (Modernizr.csstransforms && Modernizr.csstransitions) {
    // vendor prefixes omitted here for brevity
    elem.style.transition = 'all 3s ease-out';
    elem.style.transform = 'translateX(600px)';

  } else {
    // if an older browser, fall back to jQuery animate
    jQuery(elem).animate({ 'left': '600px'}, 3000);
  }
}
</script>

Usamos o Modernizr para apresentar o teste para Transformações CSS 2D e Transições CSS. Se for o caso, vamos usar a tradução para mudar a posição. Se a animação for feita usando uma transição, há uma boa chance de que o navegador possa acelerá-la por hardware. Para impulsionar o navegador novamente para a direção certa, usaremos a "bala mágica do CSS" acima.

Se nosso navegador tiver menos capacidade, usaremos o jQuery para mover nosso elemento. Você pode usar o plug-in de polyfill de transformação jQuery de Louis-Remi Babe para tornar tudo automático.

window.requestAnimationFrame

O requestAnimationFrame foi apresentado pelo Mozilla e iterado pelo WebKit com o objetivo de fornecer uma API nativa para executar animações, sejam elas baseadas em DOM/CSS ou em <canvas> ou WebGL. O navegador pode otimizar animações simultâneas juntas em um único ciclo de reflow e repintura, levando a uma animação de maior fidelidade. Por exemplo, animações baseadas em JS sincronizadas com transições CSS ou SVG SMIL. Além disso, se você estiver executando o loop de animação em uma guia não visível, o navegador não a manterá em execução, o que significa menos uso de CPU, GPU e memória, levando a uma duração muito maior da bateria.

Para mais detalhes sobre como e por que usar requestAnimationFrame, consulte o artigo requestAnimationFrame for smart animating (link em inglês) de Paul Irlanda.

Caracterização de perfil

Quando você descobrir que a velocidade do seu aplicativo pode ser aprimorada, é hora de investigar a criação de perfil para descobrir onde as otimizações poderiam gerar mais benefícios. As otimizações costumam ter um impacto negativo na manutenção do código-fonte e, portanto, só devem ser aplicadas se necessário. A criação de perfil informa quais partes do seu código teriam mais benefícios quando o desempenho fosse melhorado.

Caracterização de perfil JavaScript

Os criadores de perfil do JavaScript oferecem uma visão geral do desempenho de seu aplicativo no nível da função JavaScript medindo o tempo necessário para executar cada função individual do início ao fim.

O tempo bruto de execução de uma função é o tempo total necessário para executá-la de cima para baixo. O tempo líquido de execução é o tempo bruto menos o tempo necessário para executar funções chamadas a partir da função.

Algumas funções são chamadas com mais frequência que outras. Os criadores de perfil geralmente informam o tempo necessário para todas as invocações serem executadas, assim como os tempos de execução médio, mínimo e máximo.

Para mais detalhes, consulte os documentos do Chrome Dev Tools sobre a criação de perfis.

O DOM

O desempenho do JavaScript tem forte influência na fluidez e na resposta do aplicativo. É importante entender que, embora os criadores de perfil JavaScript meçam o tempo de execução de seu JavaScript, eles também medem indiretamente o tempo gasto realizando operações DOM. Muitas vezes, essas operações do DOM estão no centro dos problemas de desempenho.

function drawArray(array) {
  for(var i = 0; i < array.length; i++) {
    document.getElementById('test').innerHTML += array[i]; // No good :(
  }
}

Por exemplo, no código acima, quase nenhum tempo é gasto executando o JavaScript real. Ainda é muito provável que a função drawArray seja exibida em seus perfis porque está interagindo com o DOM de maneira que desperdiçava.

Dicas e truques

Funções anônimas

Funções anônimas não são fáceis de criar perfis, pois inerentemente não têm um nome sob o qual podem aparecer no criador de perfil. Há duas maneiras de lidar com isso:

$('.stuff').each(function() { ... });

reescrever para:

$('.stuff').each(function workOnStuff() { ... });

Não se sabe que o JavaScript oferece suporte a expressões de função de nomenclatura. Isso fará com que elas apareçam perfeitamente no criador de perfil. Há um problema com essa solução: a expressão nomeada na verdade coloca o nome da função no escopo lexical atual. Isso pode danificar outros símbolos, então tenha cuidado.

Criação de perfil de funções longas

Imagine que você tem uma função longa e suspeita que uma pequena parte dela pode ser a causa dos problemas de desempenho. Há duas maneiras de descobrir qual parte é o problema:

  1. O método correto: refatorar seu código para não incluir funções longas.
  2. O método maldoso de conseguir fazer as coisas: adicionar declarações no formato de funções de autochamada nomeadas ao seu código. Se você tiver um pouco de cuidado, isso não vai mudar a semântica e fazer partes da sua função aparecerem como funções individuais no criador de perfil: js function myLongFunction() { ... (function doAPartOfTheWork() { ... })(); ... } Não se esqueça de remover essas funções extras depois que a criação do perfil for concluída ou até mesmo usá-las como ponto de partida para refatorar o código.

Criação de perfil DOM

As ferramentas de desenvolvimento mais recentes do Chrome Web Inspector contêm a nova "Visualização da linha do tempo", que mostra uma linha do tempo das ações de baixo nível realizadas pelo navegador. Use essas informações para otimizar as operações DOM. Procure reduzir o número de "ações" que o navegador precisa realizar enquanto seu código é executado.

A visualização da linha do tempo pode criar uma imensa quantidade de informações. Portanto, tente criar casos de teste mínimos que possam ser executados de forma independente.

Criação de perfil DOM

A imagem acima mostra a saída da visualização da linha do tempo de um script muito simples. O painel esquerdo mostra as operações realizadas pelo navegador em ordem cronológica, enquanto a linha do tempo no painel direito mostra o tempo real consumido por uma operação individual.

Mais informações sobre a visualização em linha do tempo. Uma ferramenta alternativa para criação de perfis no Internet Explorer é o DynaTrace Ajax Edition.

Estratégias de criação de perfil

Identificar aspectos

Quando você quiser criar um perfil do aplicativo, tente destacar o mais próximo possível os aspectos da funcionalidade dele que podem acionar a lentidão. Em seguida, tente executar um perfil que execute apenas partes do código relevantes para esses aspectos do aplicativo. Isso facilitará a interpretação dos dados de criação de perfil, porque eles não são misturados com caminhos de código que não estão relacionados ao problema real. Bons exemplos para aspectos individuais do seu aplicativo podem ser:

  1. Tempo de inicialização (ativar o criador de perfil, recarregar o aplicativo, aguardar a conclusão da inicialização, parar o criador de perfil).
  2. Clicar em um botão e na animação subsequente (iniciar criador de perfil, clicar no botão, aguardar até que a animação seja concluída, parar criador de perfil).
Criação de perfil da GUI

Executar apenas a parte certa do seu aplicativo pode ser mais difícil em um programa GUI do que quando se otimiza, digamos, o traçador de raios do mecanismo 3D. Quando, por exemplo, você quer criar um perfil do que acontece ao clicar em um botão, é possível acionar eventos de mouseover não relacionados no caminho, que tornam os resultados menos conclusivos. Tente evitar isso :)

Interface programática

Há também uma interface programática para ativar o depurador. Isso permite um controle preciso sobre quando a criação de perfil começa e termina.

Inicie uma criação de perfil com:

console.profile()

Interrompa a criação de perfil com:

console.profileEnd()

Repetibilidade

Ao criar o perfil, certifique-se de conseguir reproduzir seus resultados. Só assim será possível saber se as otimizações realmente melhoraram as coisas. Além disso, a criação de perfil no nível da função é feita no contexto de todo o computador. Não é uma ciência exata. A execução de perfis individuais pode ser influenciada por muitas outras coisas que acontecem no seu computador:

  1. Um timer não relacionado no seu próprio aplicativo que é acionado enquanto você mede outra coisa.
  2. O coletor de lixo fazendo seu trabalho.
  3. Outra guia do seu navegador fazendo um trabalho pesado na mesma linha de execução.
  4. Outro programa em seu computador usando a CPU e tornando seu aplicativo mais lento.
  5. Mudanças repentinas no campo gravitacional da Terra.

Também faz sentido executar o mesmo caminho de código várias vezes em uma sessão de criação de perfil. Dessa forma, você diminui a influência dos fatores acima e as partes lentas podem se destacar ainda mais claramente.

Medir, melhorar, medir

Quando você identificar um ponto lento em seu programa, tente pensar em maneiras de melhorar o comportamento de execução. Depois de mudar o código, crie o perfil novamente. Se estiver satisfeito com o resultado, siga em frente. Se não houver melhoria, você provavelmente deverá reverter a alteração e não deixá-la como "porque não faz mal".

Estratégias de otimização

Minimizar interação do DOM

Um tema comum para melhorar a velocidade de aplicativos cliente da Web é minimizar a interação do DOM. Embora a velocidade dos mecanismos JavaScript tenha aumentado em uma ordem de magnitude, o acesso ao DOM não foi mais rápido na mesma taxa. Isso também acontece por razões muito práticas (coisas como definir o layout e desenhar coisas em uma tela levam tempo).

Armazenar nós DOM em cache

Sempre que você recuperar um nó ou uma lista de nós do DOM, pense se é possível reutilizá-los em um cálculo posterior (ou mesmo na próxima iteração de loop). Desde que você não adicione ou exclua nós na área relevante, isso geralmente acontece.

Antes:

function getElements() {
  return $('.my-class');
}

Depois:

var cachedElements;
function getElements() {
  if (cachedElements) {
    return cachedElements;
  }
  cachedElements = $('.my-class');
  return cachedElements;
}

Armazenar valores de atributo em cache

Da mesma maneira que você armazena nós DOM em cache, também pode armazenar os valores dos atributos em cache. Imagine que você está animando um atributo do estilo de um nó. Se você sabe que você (como essa parte do código) é o único que vai tocar nesse atributo, pode armazenar em cache o último valor em cada iteração para que não tenha que lê-lo repetidamente.

Antes:

setInterval(function() {
  var ele = $('#element');
  var left = parseInt(ele.css('left'), 10);
  ele.css('left', (left + 5) + 'px');
}, 1000 / 30);

Depois: js var ele = $('#element'); var left = parseInt(ele.css('left'), 10); setInterval(function() { left += 5; ele.css('left', left + 'px'); }, 1000 / 30);

Tirar a manipulação DOM dos loops

Loops geralmente são pontos importantes para otimização. Tente pensar em maneiras de dissociar o processamento de números reais para trabalhar com o DOM. Muitas vezes, é possível fazer um cálculo e, em seguida, aplicar todos os resultados de uma só vez.

Antes:

document.getElementById('target').innerHTML = '';
for(var i = 0; i < array.length; i++) {
  var val = doSomething(array[i]);
  document.getElementById('target').innerHTML += val;
}

Depois:

var stringBuilder = [];
for(var i = 0; i < array.length; i++) {
  var val = doSomething(array[i]);
  stringBuilder.push(val);
}
document.getElementById('target').innerHTML = stringBuilder.join('');

Redesenhar e realizar reflows

Conforme discutido anteriormente, o acesso ao DOM é relativamente lento. Ele se torna muito lento quando o código lê um valor que precisa ser recalculado porque ele modificou recentemente algo relacionado no DOM. Portanto, evite misturar acesso de leitura e gravação ao DOM. O ideal é que seu código sempre seja agrupado em duas fases:

  • Fase 1: leia os valores DOM necessários para seu código
  • Fase 2: modificar o DOM

Tente não programar um padrão como:

  • Fase 1: ler os valores do DOM
  • Fase 2: modificar o DOM
  • Fase 3: ler um pouco mais
  • Fase 4: modificar o DOM em outro lugar.

Antes:

function paintSlow() {
  var left1 = $('#thing1').css('left');
  $('#otherThing1').css('left', left);
  var left2 = $('#thing2').css('left');
  $('#otherThing2').css('left', left);
}

Depois:

function paintFast() {
  var left1 = $('#thing1').css('left');
  var left2 = $('#thing2').css('left');
  $('#otherThing1').css('left', left);
  $('#otherThing2').css('left', left);
}

Essa recomendação deve ser considerada para ações que acontecem dentro de um contexto de execução do JavaScript. (Por exemplo, dentro de um manipulador de eventos, em um manipulador de intervalos ou ao lidar com uma resposta Jupyter.)

Executar a função paintSlow() acima cria esta imagem:

paintSlow()

Alternar para a implementação mais rápida resulta nesta imagem:

Implementação mais rápida

Essas imagens mostram que reordenar a maneira como seu código acessa o DOM pode melhorar muito o desempenho de renderização. Nesse caso, o código original terá que recalcular os estilos e o layout da página duas vezes para criar o mesmo resultado. Uma otimização semelhante pode ser aplicada a basicamente todos os códigos do "mundo real" e produz resultados realmente impressionantes.

Leia mais: Rendering: repaint, reflow/relayout, restyle, de Stoyan Stefanov

Redesenhos e o loop de eventos

A execução do JavaScript no navegador segue um modelo de "Loop de evento". Por padrão, o navegador fica em um estado "inativo". Esse estado pode ser interrompido por eventos de interações do usuário, por exemplo, timers do JavaScript ou callbacks do Ajax. Sempre que um JavaScript é executado nesse ponto de interrupção, o navegador normalmente espera até que ele termine de pintar a tela (pode haver exceções para JavaScripts com execução extremamente longa ou em casos como caixas de alerta que interrompem efetivamente a execução do JavaScript).

Consequências

  1. Se os seus ciclos de animação do JavaScript demorarem mais do que 1/30 segundos para serem executados, você não poderá criar animações suaves, pois o navegador não pintará novamente durante a execução do JS. Quando você espera processar eventos de usuário também, precisa ser muito mais rápido.
  2. Às vezes, é útil atrasar um pouco algumas ações do JavaScript. Por exemplo, setTimeout(function() { ... }, 0) Isso instrui o navegador a executar o callback assim que o loop de eventos ficar inativo novamente (alguns navegadores esperam pelo menos 10 ms). Você precisa estar ciente de que isso criará dois ciclos de execução do JavaScript que estão muito próximos no tempo. Ambos podem acionar uma repintura da tela, o que pode dobrar o tempo total gasto com a pintura. A heurística do navegador vai acionar duas exibições ou não.

Versão normal:

function paintFast() {
  var height1 = $('#thing1').css('height');
  var height2 = $('#thing2').css('height');
  $('#otherThing1').css('height', '20px');
  $('#otherThing2').css('height', '20px');
}
Redesenhos e o loop de eventos

Vamos adicionar um atraso:

function paintALittleLater() {
  var height1 = $('#thing1').css('height');
  var height2 = $('#thing2').css('height');
  $('#otherThing1').css('height', '20px');
  setTimeout(function() {
    $('#otherThing2').css('height', '20px');
  }, 10)
}
Delay

A versão atrasada mostra que o navegador pinta duas vezes, embora as duas mudanças na página sejam apenas 1/100 de segundo por parte.

Inicialização lenta

Os usuários querem apps da Web com carregamento rápido e responsivos. No entanto, os usuários têm diferentes limites para o que percebem como lento dependendo da ação que realizam. Por exemplo, um app nunca deve fazer muitos cálculos em um evento de mouseover, porque isso pode criar uma experiência do usuário ruim enquanto o usuário continua movendo o mouse. No entanto, os usuários costumam aceitar um pequeno atraso depois de clicar em um botão.

Portanto, pode fazer sentido mover o código de inicialização para que ele seja executado o mais tarde possível (por exemplo, quando o usuário clica em um botão que ativa um componente específico do aplicativo).

Antes: js var things = $('.ele > .other * div.className'); $('#button').click(function() { things.show() });

Depois: js $('#button').click(function() { $('.ele > .other * div.className').show() });

Delegação de eventos

A propagação de manipuladores de eventos em uma página pode levar um tempo relativamente longo e também ser tediosa, uma vez que os elementos são substituídos dinamicamente, o que requer a reconexão dos manipuladores de evento aos novos elementos.

Nesse caso, a solução é usar uma técnica chamada delegação de eventos. Em vez de anexar manipuladores de eventos individuais a elementos, a natureza de propagação de muitos eventos de navegador é usada, na verdade, anexando o manipulador de eventos a um nó pai e verificando o nó de destino do evento para ver se o evento é de interesse.

No jQuery, isso pode ser facilmente expresso como:

$('#parentNode').delegate('.button', 'click', function() { ... });

Quando não usar delegação de eventos

Às vezes, o oposto pode ser verdadeiro: você está usando uma delegação de eventos e está tendo um problema de desempenho. Basicamente, a delegação de eventos permite um tempo de inicialização de complexidade constante. No entanto, o preço de verificar se um evento é de interesse precisa ser pago para cada invocação desse evento. Isso pode sair caro, especialmente para eventos que ocorrem com frequência, como "mouseover" ou mesmo "mousemove".

Problemas e soluções típicos

O que eu faço no $(document).ready leva muito tempo

Conselho pessoal do Malte: nunca faça nada em $(document).ready. Tente entregar o documento na forma final. Ok, você tem permissão para registrar listeners de eventos, mas usando apenas o seletor de IDs e/ou a delegação de eventos. Para eventos caros, como "mousemove", atrase o registro até que sejam necessários (evento mouseover no elemento relevante).

E se você realmente precisa fazer alguma coisa, como fazer uma solicitação Ajax para obter dados reais, então mostre uma animação legal; você pode querer incluir a animação como um URI de dados, se for um GIF animado ou algo semelhante.

Desde que adicionei um filme em Flash à página, tudo está muito lento

Adicionar o Flash a uma página sempre diminuirá um pouco a velocidade da renderização, porque o layout final da janela deve ser "negociado" entre o navegador e o plug-in do Flash. Quando você não puder evitar completamente a inserção do Flash em suas páginas, defina o parâmetro Flash "wmode" para o valor "window" (que é o padrão). Isso desativa a capacidade de compor elementos HTML e Flash (você não poderá ver um elemento HTML que está acima do filme em Flash, e o filme em Flash não pode ser transparente). Isso pode ser inconveniente, mas vai melhorar muito o desempenho. Por exemplo, confira como o youtube.com evita colocar camadas acima do player de filme principal.

Estou salvando coisas no localStorage, agora meu aplicativo trava

Gravar no localStorage é uma operação síncrona que envolve girar o disco rígido. Nunca convém realizar operações síncronas de "longa duração" ao fazer animações. Mova o acesso a localStorage para um ponto no código em que você tenha certeza de que o usuário está inativo e que nenhuma animação está acontecendo.

A criação de perfil aponta para um seletor jQuery muito lento

Primeiro, você precisa garantir que seu seletor possa ser executado por meio de document.querySelectorAll. Teste isso no Console JavaScript. Se houver uma exceção, reescreva seu seletor para não usar nenhuma extensão especial da sua estrutura de JavaScript. Isso acelera o seletor em uma ordem de grandeza em navegadores modernos.

Se isso não ajudar ou se você também quiser aumentar a velocidade em navegadores mais recentes, siga estas diretrizes:

  • Seja o mais específico possível no lado direito do seletor.
  • Use um nome de tag que você não usa com frequência como a parte do seletor mais à direita.
  • Se nada ajudar, reescreva as coisas para que você possa usar um seletor de id

Todas essas manipulações de DOM levam muito tempo

Várias inserções, remoções e atualizações de nós DOM podem ser muito lentas. Geralmente, isso pode ser otimizado gerando uma grande string de HTML e usando domNode.innerHTML = newHTML para substituir o conteúdo antigo. Isso pode ser muito ruim para a manutenção e pode criar links de memória no IE, portanto, tenha cuidado.

Outro problema comum é que seu código de inicialização pode criar vários códigos HTML. Por exemplo, um plug-in jQuery que transforma uma caixa de seleção em vários divs porque é isso que a equipe de design queria, ignorando as práticas recomendadas de UX. Se você realmente quiser que sua página seja rápida, nunca faça isso. Em vez disso, entregue todas as marcações do lado do servidor em seu formato final. Isso gera muitos problemas, então pense bem se a velocidade vale a troca.

Ferramentas

  1. JSPerf: comparar pequenos snippets de JavaScript
  2. Modelo de criação de perfil no Firefox (em inglês)
  3. Ferramentas para desenvolvedores do Google Chrome (disponíveis como WebInspector no Safari)
  4. DOM Monster - para otimizar o desempenho do DOM
  5. DynaTrace Ajax Edition: para criação de perfis e otimizações de pintura no Internet Explorer

Leia mais

  1. Velocidade do Google
  2. Paul Ireland sobre o desempenho do jQuery
  3. Desempenho extremo em JavaScript (apresentação de slides)