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

Introdução

Grande parte do HTML5 tem como objetivo oferecer suporte nativo ao navegador para componentes e técnicas que alcançamos até agora com as bibliotecas JavaScript. O uso desses recursos, quando presentes, pode oferecer uma experiência muito mais rápida aos usuários. Neste tutorial, não vamos resumir a excelente pesquisa de performance que você viu no site Exceptional Performance do Yahoo ou nos documentos do PageSpeed e no site Let's make the web faster do Google. Em vez disso, vou me concentrar em como usar HTML5 e CSS3 hoje pode tornar seus apps da Web mais responsivos.

Dica 1: use o armazenamento da Web em vez de 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 do cookie são adicionados a cada cabeçalho de solicitação HTTP. Isso pode acabar tendo um impacto mensurável no tempo de resposta, especialmente durante XHRs. Portanto, uma prática recomendada é reduzir o tamanho do cookie. No HTML5, podemos fazer melhor: use sessionStorage e localStorage em vez de cookies.

Esses dois objetos de armazenamento da Web podem ser usados para manter os dados do usuário no lado do cliente durante a sessão ou indefinidamente. Os dados também não são transferidos para o servidor por cada solicitação HTTP. Eles têm uma API que vai fazer você se livrar dos cookies. Confira as duas APIs, usando cookies como substituto.

// 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ções JavaScript

As transições CSS oferecem uma transição visual atraente entre dois estados. A maioria das propriedades de estilo pode ser transferida, como manipular a sombra do texto, a posição, o plano de fundo ou a cor. É possível usar transições em estados de pseudoseletores, como :hover ou de formulários HTML5, :invalid e :valid (exemplo com estados de validação de formulário). No entanto, elas são muito mais poderosas e podem ser acionadas 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 o de uma biblioteca de animação JavaScript. O número de bytes enviados para o navegador é muito menor ao usar a animação baseada em CSS. Além disso, com a aceleração no nível da GPU, essas transições visuais serão o mais suaves possível.

Dica 3: use bancos de dados do lado do cliente em vez de roundtrips do servidor

O banco de dados SQL da Web e o IndexedDB introduzem bancos de dados no lado do cliente. Em vez do padrão comum de postar dados no servidor por XMLHttpRequest ou envio de formulário, você pode aproveitar esses bancos de dados do lado do cliente. A redução de solicitações HTTP é uma meta principal de todos os engenheiros de performance. Usar essas solicitações como um repositório de dados pode economizar muitas viagens por XHR ou postagens de formulários de volta ao servidor. localStorage e sessionStorage podem ser usados em alguns casos, como a captura do progresso do envio de formulários, e são consideravelmente mais rápidos do que as APIs de 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 vai economizar ida e volta de HTTP quando o usuário quiser pesquisar, filtrar ou classificar. Uma lista de amigos ou um preenchimento automático de entrada de texto pode ser filtrado em cada tecla pressionada, o que torna a experiência do usuário muito mais responsiva.

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

Muitos métodos adicionais foram adicionados ao protótipo de matriz no JavaScript 1.6. Elas 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 o laço for típico, como for (var i = 0, len = arr.length; i &lt; len; i++). A análise JSON nativa (usando JSON.parse()) substitui o arquivo json2.js que usamos 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 do que os equivalentes de JS longos, além de potencialmente mais correto. Tecnicamente, nenhuma dessas adições de JavaScript é HTML5, mas elas se enquadram no guarda-chuva de tecnologias que estão sendo disponibilizadas recentemente.

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

Há dois anos, o WordPress usou o Google Gears para adicionar um recurso chamado WordPress Turbo. Ele armazena em cache muitos dos recursos usados no painel de administração localmente, acelerando o acesso aos arquivos. Podemos 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 que indica os recursos estáticos que podem ser armazenados em cache, os navegadores podem otimizar isso bastante, talvez até mesmo armazenando em cache antes do uso. Considere a estrutura básica do seu site como um modelo. Você tem dados que podem mudar, mas o HTML em torno deles geralmente permanece bastante consistente. Com o cache do app, você pode tratar o HTML como uma série de modelos puros, armazenar a marcação em cache pelo cache.manifest e, em seguida, enviar JSON pela rede para atualizar o conteúdo. Esse modelo é muito semelhante ao que um app de notícias nativo do iPhone ou Android faz.

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

Em navegadores líderes, 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 o IE9, e o Safari adicionou a aceleração no nível do hardware na versão 5. Ele chegou ao Safari para dispositivos móveis muito antes. O Chromium adicionou 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 só é ativada em um conjunto bastante restrito de condições, mas as transformações 3D e a opacidade animada são as maneiras mais comuns de ativar o interruptor. Uma maneira um tanto hackeada, mas discreta, de ativar essa opção é:

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

Mas não há garantias. :) Com a aceleração de hardware ativada e com suporte, a tradução, a rotação, a escala e a opacidade animadas vão ficar mais suaves com a composição de GPU. Eles têm a vantagem de serem processados diretamente na GPU e não precisam redesenhar o conteúdo da camada. No entanto, qualquer propriedade que afete o layout da página ainda será relativamente lenta.

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

Os workers da Web têm dois benefícios significativos: 1) Eles são rápidos. 2) Enquanto eles executam as tarefas, o navegador continua responsivo. Confira a apresentação de slides HTML5 para trabalhadores 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
  • Processar matrizes grandes

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

O HTML5 apresenta um novo conjunto de tipos de entrada, atualizando o 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 do navegador varia, e o Opera é o que mais implementa esse recurso no momento. Com a detecção de recursos, é possível determinar se o navegador tem suporte nativo (e oferece uma interface como um seletor de data ou de cores). Caso contrário, você pode continuar usando os widgets JS para realizar essas tarefas comuns. Além dos tipos, alguns recursos úteis foram adicionados aos nossos campos de entrada normais. A entrada placeholder oferece um texto padrão que é limpo quando você clica nela, e autofocus foca a seta no carregamento da página para que você possa interagir imediatamente com esse campo. A validação de entrada é outra coisa que está chegando com o HTML5. Adicionar o atributo required significa que o navegador não vai permitir que o formulário seja enviado até que esse campo seja preenchido. Além disso, o atributo pattern permite especificar uma expressão regular personalizada para a entrada a ser testada, com valores inválidos que bloqueiam o envio do formulário. Essa sintaxe declarativa é um grande upgrade não apenas 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 oferecer uma solução alternativa se não houver suporte nativo para eles. Usar os widgets nativos significa que você não precisa enviar o javascript e o css pesados necessários para extrair esses widgets, acelerando o carregamento da 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 imagem pesados

O CSS3 oferece muitas novas possibilidades de estilo que substituem o uso de imagens para representar o design visual com precisão. Substituir uma imagem de 2 KB por 100 bytes de CSS é uma grande vitória, sem mencionar que você removeu outra solicitação HTTP. Algumas propriedades para você se familiarizar são:

  • Gradientes lineares e radiais
  • Border-radius para cantos arredondados
  • Box-shadow para sombras projetadas e brilho
  • RGBA para opacidade alfa
  • Transformações para rotação
  • Máscaras CSS

Por exemplo, é possível criar botões sofisticados com gradientes e replicar muitos outros efeitos sem imagens. O suporte do navegador para a maioria deles é muito sólido, e você pode usar uma biblioteca como a Modernizr para detectar navegadores que não oferecem suporte aos recursos para usar imagens em um caso de fallback.

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

Os WebSockets foram criados em resposta à crescente popularidade do Comet. Há vantagens em usar WebSockets agora, em vez do modelo Comet sobre XHR.

Os WebSockets têm um enquadramento muito leve, e a largura de banda que eles consomem geralmente é menor do que a do XHR. Alguns relatórios indicam uma redução de 35% nos bytes enviados pela rede. Além disso, em um volume maior, a diferença de desempenho no envio de mensagens é mais aparente. O XHR foi registrado neste teste com um tempo agregado 3.500% maior do que os WebSockets. Por fim, os Labs da Ericsson consideraram o desempenho dos WebSockets e descobriram que os tempos de ping por HTTP eram de três a cinco vezes maiores do que por WebSockets devido a requisitos de processamento mais substanciais. 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 do Firefox Page Speed e YSlow. Além disso, o Speed Tracer para Chrome e o DynaTrace Ajax para IE fornecem um nível mais detalhado de registro de análise.