Andei meio sumido, mas para compensar, o post de hoje traz inúmeras dicas de como aumentar a performance dos seus sites, independentes de qual plataforma eles executam ou em qual linguagem eles são desenvolvidos. No final das contas tudo vira HTML e a comunicação é feita via protocolo HTTP. Existem muito mais dicas do que as apresnetadas aqui, listei apenas as de uso mais comum e que se aplicam à maioria dos sites. Muitas destas dicas somente fazem efeito quando seu site possui um número expressivo de acessos, então não espere que seu blog desconhecido mostre sinais de super desempenho ao utilizar quaisquer das dicas abaixo. As dicas estão divididas em categorias:
Reduza as requisições HTTP
80% do tempo de resposta ao usuário final é gasto na apresentação do site (front-end). A maioria deste tempo é peridod baixando todos os componentes na página: imagens, folhas de estilo, scripts, Flash, etc. Reduzindo o número de componentes reduz por sua vez o número de requisições HTTP necessárias para renderizar a página. Esta é a chave para páginas mais velozes.
Uma vez que você reduza o número de componentes na página você estará simplificando o projeto da mesma. Mas existe alguma maneira de criar páginas com conteúdo rico enquanto mantém tempos curtos de resposta? Existem algumas técnicas para reduzir o número de requisições HTTP, enquanto se preserva os projetos de páginas ricas.
Arquivos combinados são uma maneira de reduzir o número de requisições HTTP combinando todos os scripts em um único arquivo de scripts, e similarmente combinando todos os CSS em uma única folha de estilos. Combinar arquivos é bem desafiador quando os scripts e folhas de estilo variam de página para página, mas fazê-lo antes de lançar seu site vai melhorar o tempo de resposta das páginas.
CSS Sprites são o método preferido para reduzir o número de imagens requisitadas. Combine suas imagens de fundo em uma única imagem e use as propriedades de CSS background-image e background-position para exibir o segmento desejado da imagem.
Image maps combinam múltiplas imagens em uma única imagem. O tamanho total será o mesmo, mas reduzirá o número de requisições HTTP, acelerando a página. Image maps somenete funcionam se as imagens são contíguas na página, como uma barra de navegação. Definir as coordenadas de image maps pode ser monótona e com chance de erro. Usar image maps para navegação não é acessível também, logo não é recomendado.
Inline images usam o esquema data: URL para embutir os dados da imagem na página atual. Isto pode aumentar o tamanho de seu HTML. Combinar inline images dentro de suas folhas de estilo (armazenadas em cache) é uma maneira de reduzir as requisições HTTP e prevenir o aumento de tamanho de suas páginas. Inline images tamabém não são suportadas na maioria dos browsers.
Reduzir o número de requisições HTTP na sua página é a primeira coisa a se fazer quando o assunto é performance. É a parte mais importante de uma otimização de desempenho quando estamos falando de visitantes de primeira viagem. Os números de diversas pesquisas indicam que 40-60% dos visitantes diários de seu site estão com o cache vazio. Tornar a sua página rápida para estes visitantes de primeira viagem é a chave para uma melhor experiência do usuário.
Utilize os cabeçalhos Expires e Cache-Control
Existem dois aspectos para esta regra:
- Para componentes estáticos: implemente a política "Never expire" configurando o cabeçalho Expires para um futuro distante
- Para componentes dinâmicos: use um cabeçalho Cache-Control apropriado para ajudar o browser com requisições condicionais
Projetos de Web pages estão se tornando cada vez mais ricos, o que significa mais scripts, folhas de estilo, imagens e animações na página. Um visitante de primeira viagem que chegar na sua página terá de realizar diversas requisições HTTP, porém utilizando o cabeçalho Expires você pode tornar estes componentes armazenáveis em cache. Isto previne requisições HTTP desnecessárias em visualizações de página subsequentes. Os cabeçalhos Expires são muitas vezes utilizados com imagens, mas eles devem ser usados em todos componentes incluindo scripts, folhas de estilo e componentes Flash.
Browsers (e proxies) usam cache para reduzir o número e tamanho das requisições HTTP, tornando o carregamento das páginas mais rápido. Um webserver utiliza o cabeçalho Expires na resposta HTTP para dizer ao cliente por quanto tempo um componente pode ser armazenado em cache. Este é um cabeçalho com expiração muito distante, dizendo ao browser que esta resposta não deve ser removida de cache até 15 de abril de 2012.
Expires: Sun, 15 Apr 2012 20:00:00 GMT
Se o seu servidor é Apache, use a diretiva ExpiresDefault para definir uma data de expiração relativa à data atual. Este exemplo de diretiva ExpiresDefault define a data de expiração para daqui a 10 anos, a partir do instante da requisição.
ExpiresDefault "access plus 10 years"
Tenha em mente, se você usar um cabeçalho para expiração futura você terá de trocar o nome do arquivo do componente toda vez que o componente for alterado. Geralmente as empresas o fazem como parte do processo de lançamento de uma nova versão do site: um número de versão do arquivo é incluído no nome do arquivo, por exemplo, luiztools_2.0.6.js.
Usar um cabeçalho de expiração futura afeta somente as visualizações de página feitas depois da primeira visita do usuário ao seu site. Não há efeito algum quando o usuário visita seu site pela primeira vez e o cache do browser está vazio. Entretanto o impacto desta melhoria de performance depende de quantas vezes os usuários acessam suas páginas com o cache cheio. Através do uso do cabeçalho Expires, você aumenta o número de componentes que são armazenados em cache pelo browser e re-utiliza em subsequentes visualizações de página sem enviar um único byte através da conexão de Internet.
Componentes GZip
O tempo de transferir uma requisição e uma resposta HTTP pela rede pode ser significativamente reduzido por decisões feitas no front-end do webmaster. É verdade que a largura de banda do usuário-final, provedor de Internet, proximidade dos roteadores, etc. estão além do controle do time de desenvolvimento. mas há outras variáveis que afetam os tempos de resposta. A compressão reduz os tempos de resposta diminuindo o tamanho da resposta HTTP.
Iniciando com HTTP/1.1, os clientes web indicam suporte à compressão com o cabeçalho Accept-Encoding na requisição HTTP.
Accept-Encoding: gzip, deflate
Se o servidor web vê este cabeçalho na requisição, ele pode comprimir a resposta usando um dos métodos listados pelo cliente. O servidor web notifica o cliente web disto via cabeçalho Content-Encoding na resposta.
Content-Encoding: gzip
Gzip é o método de compressão mais popular e efetivo atualmente. Ele foi desenvolvido pelo projeto GNU e padronizado pela RFC 1952. Outro método de compressão existente é o deflate, mas ele é menos eficiente e menos popular.
Gzipar geralmente reduz o tamanho da resposta em cerca de 70%. Aproximadamente 90% do tráfico atual de Internet que viaja através dos browsers suportam gzip. Se você usa Apache, o módulo de configuração do gzip depende de sua versão: Apache 1.3 usa mod_gzip enquanto Apache 2.x usa mod_deflate.
Existem problemas conhecidos com browsers e proxyies que podem causar problemas com compressão HTTP, felizmente estes problemas estão restritor à usuários de browsers antigos.
Servidores escolhem o que será comprimido, baseado no tipo de arquivo. tipicamente eles são bem limitados e a maioria dos sites somente zipa seus documentos HTML. Também é possível zipar seus scripts e stylesheets, mas muitos sites perdem essa oportunida. Na verdade é possível comprimir qualquer texto incluindo XML e JSON. Imagens e arquivos PDF não devem ser zipados porque eles já estão em formatos comprimidos. Tentar diminuir ainda mais seu tamanho não somente irá gastar CPU à toa como pode aumentar o tamanho dos arquivos.
Gzipar todos os arquivos possíveis é uma maneira fácil de reduzir o peso das páginas e acelerar a experiência do usuário..
Folhas de Estilo no Início
Colocar as folhas de estilo no HEAD do documento faz com que as páginas pareçam estar carregando mais rápido. Isto se deve ao fato de que colocando as folhas de estilo no topo da página permite que ela se renderize progressivamente.
Especialistas em front-end que cuidam de eprformance querem que uma página carregue progressivamente; isto é, nós queremos que o browser exiba algum conteúdo o mais rápido possível. isto é especialmente importante para páginas com um monte de conteúdo e para usuários com internet ruim. A importância de dar aos usuários um feedback visual, como indicadores de progresso, é largamente pesquisada e documentada. No caso de páginas web, a própria renderização da página é o melhor indicador de progresso! Quando o browser carrega a página progressivamente o usuário vai assistindo sua construção: o cabeçalho, a barra de navegação, o logo, etc. tudo serve como feedback visual para o usuário que está esperando pela página. Isto melhora bastante a experiência do usuário.
O problema em colocar as folhas de estilo próximas ao rodapé do documento é que isto proíbe a renderização progressiva em muitos browsers, incluindo o Internet Explorer. estes browsers bloqueiam a renderização para redefinir o redesenho de elementos na página, caso seus estilos sejam alterados. O usuário fica vendo uma tela em branco.
A especificação HTML claramente diz que as folhas de estilo devem ser incluídas no HEAD da página: "Diferente de A, [LINK] deve somente aparecer na seção HEAD de um documento, embora ele possa aparecer inúmeras vezes." Obter uma tela branca ou fazer a tela piscar sem estilo não valem este risco. A melhor solução é seguir a especificação HTML e carregar suas folhas de estilo no HEAD do documento.
Scripts no Final
O problema dos scripts é que eles bloqueiam downloads paralelos. A especificação HTTP/1.1 sugere que os browsers não baixem mais de dois componentes em paralelo por hostname. Se você obtém suas imagens de múltiplos hostnames, você pode obter mais de dois downloads simultâneos. Entretanto, quando um script está sendo baixado, o browser não pode iniciar outros downloads, mesmo em diferentes servidores.
Em algumas situações não é fácil mover os scripts para o final da página. Se, por exemplo, o script usar document.write para inserir parte do conteúdo da página, ele não pode ser movido para baixo da mesma. Podem existir problemas de escopo também. Em muitos casos, existem maneiras para contonrar esta situação.
Uma sugestão alternativa é utilizar scripts deferidos (deferred). O atributo DEFER indica que o script não contém document.write, e é uma dica aos browsers para que eles continuem renderizando. Infelizmente, o Firefox não suporta o atributo DEFER. No Internet Explorer, o script pode ser deferido, mas não tanto quanto desejado. Se o script puder ser deferido, ele também pode ser movido para o final da página. Isto faz com que suas páginas carreguem mais rápido..
Use CSS e Javascript externos
Muitas dessas regras de performance lidam com como os componentes externos são gerenciados. Entretanto, antes dessas considerações surgirem você deve perguntar uma questão ainda mais básica: o Javascript e CSS devem estar em arquivos externos ou na própria página?
Usar arquivos externos no mundo real geralmente produz páginas mais rápidas porque estes arquivos são mantidos em cache pelo browser. JavaScript e CSS que estão escritos no HTML são baixados cada vez que o documento é requisitado. Isto reduz o número de requisições HTTP que são necessárias, mas aumenta o tamanho do documento HTML. Por outro lado, se o JavaScript e o CSS estão em arquivos externos em cache no browser, o tamanho do HTML é reduzido sem aumentar o número de requisições HTTP.
A chave, então, é a frequência cujos componentes externos são mantidos em cache relativo ao número de documentos HTML requisitados. Este fator, embora difícil de quantificar, pode ser analisado usando várias métricas. Se os usuários de seu site tem muitos pageviews por sessão e muitas de suas páginas reusam os mesmos scripts e estilos, há um grande potencial de ser beneficiado pelo cache de arquivos externos.
Muitos web sites caem no meio dessas métricas. Para estes sites, a melhor solução geralmente é usar JavaScript e CSS em arquivos externos. A única exceção fica para as home pages, onde escrever o código JS e CSS é preferível. Home pages que possuem poucos (quase sempre um) page view por sessão pode encontrar resultados mais rápidos escrevendo JS e CSS no próprio HTML.
Minimize Javascript e CSS
Minificação é a prática de remover caracteres desnecessários do código para reduzir seu tamanho, melhorando tempos de carregamento. Quando o código é minificado todos os comentários são removidos, bem como espaços em branco desnecessários. No caso de JavaScript, isto melhora a performance porque seu tamanho é reduzido e consequentemente o tempo de download também. Duas ferramentas populares para minificar JavaScript são JSMin e YUI Compressor. O YUI Compressor também pode minificar CSS.
Ofuscação é uma alternativa de otimização que pode ser aplicada ao código fonte. Ela é mais complexa que minificação e algumas vezes gera bugs como resultado da ofuscação. Em uma pesquisa americana notou-se que códigos minificados obtém 21% de redução d etamanho, contra 25% da ofuscação. Embora a ofuscação mostre um desempenho melhor, minificar o JS tem menos risco.
Em adição à minificação de scripts e estilos, tags <script> e <style> no código também devem ser minificadas. Mesmo que você use GZip para diminuir o tamanho de seus arquivos, minificá-los ainda irá reduzir em 5% o tamanho dos mesmos, ou mais.
Evite Redirecionamentos
Redirecionamentos possuem como resposta os status 301 e 302. Aqui está um exemplo de cabeçalho HTTP de uma resposta 301:
HTTP/1.1 301 Moved Permanently
Location: http://exemplo.com.br/novaurl
Content-Type: text/html
O browser automaticamente leva o usuário para a URL especificada no campo Location. Todas as informações necessárias para o redirecionamento estão nos cabeçalhos. O corpo da resposta é tipicamente vazio. A despeito de seus nomes, nem as respostas 301 ou 302 são armazenadas em cache na prática, a menos que cabeçalhos adicionais, como Expires ou Cache-Control, indiquem que ele deva ser. A tag meta refresh e JavaScript são outras maneiras de direcionar os usuários para URLs diferentes, mas se você realmente deve realizar um redirecionamento, a técnica preferida é utilizar os códigos de status padrões do HTTP 3xx, principalmente para garantir que o botão de voltar funcione.
O importante de se lembrar é que o redirecionamento diminui a experiência do usuário. Inserir um redirecionamento entre o usuário e o HTML diminui o desempenho de qualquer site pois exigirá que nada na página apareça até que o novo documento HTML chegue.
Um dos redirecionamentos mais frequentes que acontecem os desenvolvedores web nem fazem idéia do que seja, Ele ocorre toda vez que uma barra (/) não se encontra no final de uma URL. Por exemplo, acessar a URL http://astrology.yahoo.com/astrology results resultará em uma resposta 301 contendo um redirecionamento para http://astrology.yahoo.com/astrology/ (preste atenção à barra no final).
Remova Scripts duplicados
Algo que "machuca" bastante a performance de uma página é incluir duas vezes o mesmo Javascript em uma página. Isto não é tão incomum quanto parece. Uma pesquisa realizada com os dez sites americanos mais acessadosmostraram que dois deles possuem scripts duplicados. Resumindo: JS duplicados criam requisições HTTP desnecessárias e execução de JS repetido.
Requisições HTTP desnecessárias acontecem no Internet Explorer, mas não no Firefox. No IE, se um script externo é incluído duas vezes e não é guardado em cache, ele gera duas requisições HTTP durante o carregamento da página. Mesmo que o script esteja em cache, requisições extras quando o usuário recarrega a página.
Entretanto, a execução repetida de JS acontece independente de browser, o que é um grande problema.
Uma maneira de prevenir scripts repetidos é implementar um módulo de gerenciamento de scripts no seu sistema de templates. A maneira típica de incluir scripts em uma página é a seguinte.
<script type="text/javascript" src="menu_1.0.17.js"></script>
Uma alternativa em PHP seria criar uma função chamada inserirScript.
<?php insertScript("menu.js") ?>
Além de prevenir que o mesmo script seja inserido múltiplas vezes, esta função pode gerenciar outros problemas com scripts, como checagem de dependência e tudo o mais que sua imaginação permitir.
Libere o buffer cedo
Quando um usuário requisita uma página, ela pode levar de 200 a 500ms para o servidor exibir a página HTML. Durante este tempo, o browser está ocioso e aguarda pela chegada da página. No PHP você tem a função flush() e no ASP.NET você tem o Response.Flush(). Isto permite que você envie um HTML parcial ao browser e ele já pode ir renderizando a página. O benefício é principalmente visto em backends ocupados e frontends leves.
Um bom lugar para considerar a liberação é logo depois do HEAD porque geralmente o HTML do HEAD é fácil de ser montado pelo servidor e permite que você já vá mostrando o CSS e jacascript para o browser em paralelo enquanto o backend continua processando.
Exemplo:
... <!-- css, js -->
</head>
<?php flush(); ?>
<body>
... <!-- content -->
A busca do Yahoo! foi pioneira no uso desta técnica e comprovou os benefícios da mesma.
E esta foi a primeira parte das dicas retiradas e traduzidas da Internet. Aguardem os próximos posts!