Práticas recomendadas para um aplicativo da web mais rápido com HTML5

Introdução

Grande parte do HTML5 visa fornecer suporte nativo do navegador para componentes e técnicas que alcançamos por meio de bibliotecas JavaScript até o momento. Usar esses recursos, quando presentes, pode proporcionar uma experiência muito mais rápida para os usuários. Neste tutorial, não vou recapitular a excelente pesquisa de desempenho que você viu no site de desempenho excepcional do Yahoo ou nos documentos sobre velocidade de página do Google e no site Vamos tornar a Web mais rápida. Em vez disso, vou me concentrar em como usar o HTML5 e o CSS3 atualmente pode tornar seus aplicativos da Web mais responsivos.

Dica 1: use o armazenamento da Web em vez dos cookies

Embora os cookies sejam usados para rastrear dados de usuários únicos há anos, eles têm sérias desvantagens. A maior falha é que todos os dados dos seus cookies são adicionados a cada cabeçalho de solicitação HTTP. Isso pode ter um impacto mensurável no tempo de resposta, especialmente durante os XHRs. Portanto, uma prática recomendada é reduzir o tamanho do cookie. No HTML5, podemos fazer melhor do que isso: usar sessionStorage e localStorage no lugar dos cookies.

Esses dois objetos de armazenamento da Web podem ser usados para manter dados do usuário no lado do cliente durante a sessão ou indefinidamente. Os dados deles também não são transferidos para o servidor por meio de solicitações HTTP. Eles têm uma API que vai deixar você feliz por não usar cookies. Aqui estão as duas APIs que usam cookies como substitutos.

// if localStorage is present, use that
if (('localStorage' in window) && window.localStorage !== null) {

  // easy object property API
  localStorage.wishlist = '["Unicorn","Narwhal","Deathbear"]';

} else {

  // without sessionStorage we'll have to use a far-future cookie
  //   with document.cookie's awkward API :(
  var date = new Date();
  date.setTime(date.getTime()+(365*24*60*60*1000));
  var expires = date.toGMTString();
  var cookiestr = 'wishlist=["Unicorn","Narwhal","Deathbear"];'+
                  ' expires='+expires+'; path=/';
  document.cookie = cookiestr;
}

Dica 2: use transições CSS em vez de animação JavaScript

As transições CSS oferecem uma transição visual atrativa entre dois estados. A maioria das propriedades de estilo pode sofrer transição, como ao manipular a sombra do texto, a posição, o plano de fundo ou a cor. É possível usar transições para estados de pseudosseletor, como :hover, ou de formulários HTML5, :invalid e :valid (exemplo com estados de validação de formulários). No entanto, eles são muito mais poderosos e podem ser acionados quando você adiciona qualquer classe a um elemento.

div.box {
  left: 40px;
  -webkit-transition: all 0.3s ease-out;
     -moz-transition: all 0.3s ease-out;
       -o-transition: all 0.3s ease-out;
          transition: all 0.3s ease-out;
}
div.box.totheleft { left: 0px; }
div.box.totheright { left: 80px; }

Ao adicionar a alternância das classes de totheleft e totheright, você pode mover a caixa. Compare essa quantidade de código com a de uma biblioteca de animação JavaScript. Claramente, o número de bytes enviados ao navegador é muito menor quando se usa uma animação baseada em CSS. Além disso, com a aceleração no nível da GPU, essas transições visuais são as mais suaves possível.

Dica 3: use bancos de dados do lado do cliente em vez de ida e volta do servidor

O banco de dados Web SQL e o IndexedDB apresentam os bancos de dados ao lado do cliente. Em vez do padrão comum de postagem de dados no servidor via XMLHttpRequest ou envio de formulário, é possível aproveitar esses bancos de dados do lado do cliente. A diminuição de solicitações HTTP é um alvo principal de todos os engenheiros de desempenho, portanto usá-las como um armazenamento de dados pode salvar muitas viagens por meio de XHR ou enviar envios de formulário ao servidor. localStorage e sessionStorage podem ser usadas em alguns casos, como a captura do progresso do envio de formulários, e são visivelmente mais rápidas do que as APIs do banco de dados do lado do cliente. Por exemplo, se você tiver um componente de grade de dados ou uma caixa de entrada com centenas de mensagens, armazenar os dados localmente em um banco de dados poupará idas e voltas de HTTP quando o usuário quiser pesquisar, filtrar ou classificar. Uma lista de amigos ou um preenchimento automático de entrada de texto poderia ser filtrada a cada toque de tecla, tornando a experiência do usuário muito mais responsiva.

Dica 4: melhorias no JavaScript proporcionam vantagens consideráveis de desempenho

Muitos métodos adicionais foram adicionados ao protótipo de matriz no JavaScript 1.6. Estes estão disponíveis na maioria dos navegadores, exceto no IE. Exemplo:

// Give me a new array of all values multiplied by 10.
[5, 6, 7, 8, 900].map(function(value) { return value * 10; });
// [50, 60, 70, 80, 9000]

// Create links to specs and drop them into #links.
['html5', 'css3', 'webgl'].forEach(function(value) {
  var linksList = document.querySelector('#links');
  var newLink = value.link('http://google.com/search?btnI=1&q=' + value + ' spec');
  linksList.innerHTML +=  newLink;
});


// Return a new array of all mathematical constants under 2.
[3.14, 2.718, 1.618].filter(function(number) {
  return number < 2;
});
// [1.618]


// You can also use these extras on other collections like nodeLists.
[].forEach.call(document.querySelectorAll('section[data-bucket]'), function(elem, i) {
  localStorage['bucket' + i] = elem.getAttribute('data-bucket');
});

Na maioria dos casos, o uso desses métodos nativos gera velocidades significativamente mais rápidas do que uma repetição for normal, como: for (var i = 0, len = arr.length; i &lt; len; i++). A análise JSON nativa (via JSON.parse()) substitui o arquivo json2.js que já estamos acostumados a incluir há algum tempo. O JSON nativo é muito mais rápido e seguro do que usar um script externo e já está disponível no IE8, Opera 10.50, Firefox 3.5, Safari 4.0.3 e Chrome. O String.trim nativo é outro bom exemplo de ser mais rápido que os equivalentes do JS longo, além de ser potencialmente mais correto. Nenhuma dessas adições de JavaScript é tecnicamente HTML5, mas elas se enquadram no conjunto de tecnologias que estão sendo disponibilizadas recentemente.

Dica 5: use o manifesto de cache em sites ativos, não apenas em apps off-line

Dois anos atrás, o Wordpress usou o Google Engrenagem para adicionar um recurso chamado Wordpress Turbo. Basicamente, ela armazenava em cache muitos dos recursos usados no painel de administração localmente, acelerando o acesso aos arquivos. É possível replicar esse comportamento com o applicationCache do HTML5 e o cache.manifest. O cache do app tem uma pequena vantagem em relação à configuração de cabeçalhos Expires. Como você cria um arquivo declarativo indicando os recursos estáticos que podem ser armazenados em cache, os navegadores podem otimizar muito isso, talvez até armazenando em cache antes do seu uso. Considere a estrutura básica do seu site como um modelo. Há dados que podem mudar, mas o HTML ao redor deles geralmente permanece bastante consistente. Com o cache do aplicativo, é possível tratar o HTML como uma série de modelos puros, armazenar a marcação em cache por meio do cache.manifest e, em seguida, entregar JSON pela rede para atualizar o conteúdo. Esse modelo é muito semelhante ao que um aplicativo de notícias nativo do iPhone ou Android faz.

Dica 6: ative a aceleração de hardware para melhorar a experiência visual

Nos principais navegadores, muitas operações visuais podem aproveitar a aceleração no nível da GPU, o que pode tornar as operações visuais altamente dinâmicas muito mais suaves. A aceleração de hardware foi anunciada para o Firefox Minefield e IE9 e o Safari adicionou aceleração no nível de hardware na versão 5. Ele chegou no Mobile Safari muito antes. O Chromium acabou de adicionar transformações 3D e aceleração de hardware para Windows. As outras duas plataformas serão lançadas em breve.

A aceleração da GPU é ativada apenas em condições bastante restritas, mas transformações 3D e opacidade animada são as maneiras mais comuns de acionar a chave. Esta é uma maneira um pouco hackeada, mas discreta de ativá-la, é:

.hwaccel {  -webkit-transform: translateZ(0); }

Mas não podemos garantir. :) Com a aceleração de hardware compatível e ativada, a translação animada, a rotação, o dimensionamento e a opacidade definitivamente serão mais suaves com a composição de GPU. Elas podem ser processadas diretamente na GPU e não exigem o redesenho do conteúdo da camada. No entanto, as propriedades que afetarem o layout da página ainda serão relativamente lentas.

Dica 7: para operações com uso intenso de CPU, os Web Workers fornecem

Os Web Workers têm duas vantagens significativas: 1) Eles são rápidos. 2) Enquanto elas aceleram suas tarefas, o navegador permanece responsivo. Confira a Apresentação de slides HTML5 para funcionários em ação. Algumas situações possíveis em que você pode usar Web Workers:

  • Formatação de texto de um documento longo
  • Destaque de sintaxe
  • Processamento de imagens
  • Síntese de imagens
  • Como processar matrizes grandes

Dica 8: atributos e tipos de entrada do formulário HTML5

O HTML5 introduz um novo conjunto de tipos de entrada, atualizando nosso conjunto de text, password e file para incluir search, tel, url, email, datetime, date, month, week, time, datetime-local, number, range e color. O suporte dos navegadores varia, e o Opera está sendo implementado principalmente no momento. Com a detecção de recursos, é possível determinar se o navegador tem suporte nativo (e oferecerá uma interface como um seletor de datas ou cores) e, caso contrário, você pode continuar usando os widgets JS para realizar essas tarefas comuns. Além dos tipos, alguns atributos úteis foram adicionados aos campos de entrada normais. A entrada placeholder oferece um texto padrão que é apagado quando você clica neles e autofocus foca o cursor no carregamento da página para que você possa interagir imediatamente com esse campo. A validação de entrada é outra coisa que surgiu com o HTML5. Adicionar o atributo required significa que o navegador não permitirá o envio do formulário até que o campo seja preenchido. Além disso, o atributo pattern permite especificar uma expressão regular personalizada para a entrada que vai ser testada, com valores inválidos bloqueando o envio do formulário. Essa sintaxe declarativa é um grande upgrade, não só na legibilidade da fonte, mas também uma redução significativa do JavaScript necessário. Novamente, você pode usar a detecção de recursos para disponibilizar uma solução substituta se não houver suporte nativo para eles. Usar os widgets nativos aqui significa que você não precisa enviar o JavaScript e o CSS pesados necessários para extrair esses widgets, acelerando o carregamento de página e provavelmente melhorando a capacidade de resposta do widget. Para testar algumas dessas melhorias de entrada, confira a Apresentação de slides HTML5.

Dica 9: use efeitos CSS3 em vez de solicitar sprites de imagens pesados

O CSS3 oferece muitas novas possibilidades de estilo que vão além do uso de imagens para representar o design visual com precisão. Substituir uma imagem de 2K por 100 bytes de CSS é uma grande vitória, sem contar que você removeu mais uma solicitação HTTP. Algumas das propriedades para se familiarizar são:

  • Gradientes lineares e radiais
  • Raio da borda para cantos arredondados
  • Sombra da caixa para sombras projetadas e brilho
  • RGBA para opacidade alfa
  • Transformações para rotação
  • Máscaras CSS

Por exemplo, é possível criar botões muito refinados por meio de gradientes e replicar muitos outros efeitos sem imagens. O suporte dos navegadores para a maioria deles é muito sólido. Você pode usar uma biblioteca como a Modernizr para capturar navegadores que não são compatíveis com os recursos para usar imagens em um caso substituto.

Dica 10: WebSockets para entrega mais rápida com menos largura de banda que XHR

O WebSockets foi desenvolvido em resposta à crescente popularidade do Comet (link em inglês). Há vantagens em usar WebSockets agora, em vez do modelo Comet sobre XHR.

Os WebSockets têm uma moldura muito leve e, portanto, a largura de banda que eles consomem é geralmente mais leve que a do XHR. Alguns relatórios indicam uma redução de 35% em bytes enviados pela rede. Além disso, em um volume maior, a diferença de desempenho no que se refere à entrega de mensagens é mais aparente. O XHR foi registrado neste teste com um tempo agregado de 3.500% maior que o dos WebSockets. Por fim, a Ericcson Labs considerou o desempenho dos WebSockets e descobriu que os tempos de ping no HTTP eram de três a cinco vezes maiores do que nos WebSockets devido a requisitos de processamento mais significativos. Eles concluíram que o protocolo WebSocket era claramente mais adequado para aplicativos em tempo real.

Outros recursos

Para recomendações de medição e desempenho, use as extensões Page Speed e YSlow do Firefox. Além disso, Speed Tracer para Chrome e DynaTrace Ajax para IE fornecem um nível mais detalhado de registro de análises.