Desenvolvimento

20 nov, 2012

Como otimizar aplicações web

Publicidade

As aplicações web estão cada vez mais robustas – muitas delas recebem milhões de usuários por dia -, mas será que elas realmente aguentam essa quantidade de requisições mantendo a qualidade de seus serviços?

Nosso objetivo hoje é aprender a otimizar nossas aplicações front-end para que o usuário tenha a melhor experiência possível.

Configurando nosso servidor

Para configurar nossos servidores, utilizaremos exemplos no apache, mas tudo que será explicado é valido para outros servidores, como IIS e Nginx.

Gzip

O Gzip é um software para compressão e descompressão de arquivos. Ele é altamente utilizado em websites para aumentar a performance. Sites que utilizam o o Gzip podem ser até 80% mais rápidos.

Como configuramos nossos servidores para utilizar o Gzip? Muito simples, basta informarmos ao .htaccess que queremos utilizá-lo. Exemplo:

  <IfModule mod_filter.c>
    AddOutputFilterByType DEFLATE application/atom+xml \
                                  application/javascript \
                                  application/json \
                                  application/rss+xml \
                                  application/vnd.ms-fontobject \
                                  application/x-font-ttf \
                                  application/xhtml+xml \
                                  application/xml \
                                  font/opentype \
                                  image/svg+xml \
                                  image/x-icon \
                                  text/css \
                                  text/html \
                                  text/plain \
                                  text/x-component \
                                  text/xml
  </IfModule>

Configurando o cache

Muitas vezes pensamos que o browser do cliente irá fazer o cache automático de nossa aplicação, mas precisamos informá-lo de como fazer o cache da maneira correta. Para isso utilizamos os recursos do response headers.

ETags

  • A Etag é um mecanismo para identificação de um componente em cache. Em outras palavras, um componente é identificado por uma string única e o browser pode verificar se ela foi modificada ou não;
  • O problema das Etags é que elas são geradas para um único servidor sendo inviável validá-la em outro servidor;
  • A melhor solução então é cancelar o uso da Etag, dessa forma o browser não irá verificar o componente. Isso trás uma performance significativa para o website.
# FileETag None is not enough for every server.
<IfModule mod_headers.c>
    Header unset ETag
</IfModule>
# Since we're sending far-future expires, we don't need ETags for static content.
FileETag None

Invalide o cache

  • Invalidar o cache também é uma ótima estratégia para alteração de conteúdo;
  • Podemos utilizar uma estratégia de versionamento de componentes (css, js), assim o servidor saberá quando um arquivo foi alterado e precisa ser recarregado;
  • Utilize helpers server-side para o versionamento dos arquivos.

Defina o tempo de cache para cada tipo de arquivo

  • O famoso Expires dos servidores é uma das melhores soluções para controle de cache;
  • Utilizamos diversos “tempos” diferentes para cada tipo de arquivo, por exemplo, arquivos como imagem podem ter um cache menor que um javascript.
<IfModule mod_expires.c>
 ExpiresActive on
# Favicon (cannot be renamed)
 ExpiresByType image/x-icon "access plus 1 week"
# Media: images, video, audio
 ExpiresByType image/gif "access plus 1 month"
 ExpiresByType image/png "access plus 1 month"
 ExpiresByType image/jpeg "access plus 1 month"
 ExpiresByType video/ogg "access plus 1 month"
 ExpiresByType audio/ogg "access plus 1 month"
 ExpiresByType video/mp4 "access plus 1 month"
 ExpiresByType video/webm "access plus 1 month"
# CSS and JavaScript
 ExpiresByType text/css "access plus 1 year"
 ExpiresByType application/javascript "access plus 1 year"
</IfModule>

Reduzindo as requisições

Reduzir a quantidade de requisições que a aplicação faz para nossos servidores é uma ótima solução para otimizarmos o carregamento da página, mas para isso precisamos entender como fazer isso.

  • Um browser pode carregar até três arquivos em paralelo para cada servidor;
  • Deixe os arquivos estáticos em servidores CDN com subdomínios, dessa forma o browser poderá carregar três arquivos para cada subdomínio em paralelo;
  • Exemplo: um website com nove js sendo carregados no mesmo servidor, irá carregar três deles em paralelos, depois mais três e mais três. Já com o CDN com três subdomínios, ele poderá carregar os nove em paralelo.

Minificar e unificar js e css

Essa estratégia é considerada uma das melhores para obtermos uma boa performance, o problema é que a maioria dos desenvolvedores não utiliza. Vamos entender como funciona:

Ferramentas para comprimir arquivos

  • YUI Compressor – Ferramenta de Yahoo que promete ser a mais segura e eficiente de todas;
  • Packer – Comprime JS pela web;
  • JSCompress.com – Usa JSMin ou Packer para reduzir o tamanho dos arquivos;
  • CSS Compressor – Comprime arquivos CSS;
  • Easy YUI compressor – Versão visual do YUI compressor.

Ferramentas para unificar arquivos

Normalmente, essas ferramentas são executadas em tempo de execução, elas comprimem e unificam os arquivos, logo em seguida armazenam os arquivos gerados em cache.

  • Minify – Ferramenta em PHP que utiliza a biblioteca YUI compressor;
  • Zend_Minify – API do Zend Framework para YUI compressor;
  • Easy Minify – API do Easy Framework para  YUI compressor;
  • YUI compressor for .net. – Biblioteca para .NET;
  • Ant – Biblioteca para Java.

Otimização de imagens

As imagens são os maiores responsáveis pela baixa performance de websites e aplicações. Felizmente, existem formas de contornar esse problema:

  • Não coloque imagens maiores do que o necessário;
  • Comprima as imagens;
  • Use os formatos corretos para cada ocasião;
  • Defina o tamanho e a largura da imagem no HTML;
  • Use Sprites onde possível.

Css Sprite

Sprite é uma imagem que contém outras imagens dentro dela, onde nós podemos pegá-las através do css e manipulá-la de diversas formas.

  • Diminui significativamente as requisições para o servidor;
  • As imagens são manipuladas pelo css através da posição no arquivo.

Ferramentas para compressão de imagens e criação de sprites

Boas práticas

Organização do HTML

  • Arquivos css no topo do documento – Isso irá evitar que páginas sejam carregadas sem o seu estilo, evitando problemas de “flickering” nas páginas;
  • Arquivos js no final do arquivo – O carregamento de javascript é algo bloqueante, então, se nós colocarmos no inicio da página nosso cliente ficará esperando o carregamento do js, levando mais tempo para a execução;
  • Deixe os arquivos de mesmo tipo próximos – Uma forma de otimizar o carregamento é entender como o interpretador do browser funciona, arquivos do mesmo tipo próximos um do outro será mais rápido do que intercalá-los;
  • Crie arquivos css e js externos;
  • Evite duplicação de scripts;
  • Quebre os componentes em vários subdominios;
  • Diminiua o uso de iframes – iFrames exigem novas requisiçõ~es com subrequisições, deixando a página consideravelmente lenta;
  • Mantenha seus componentes abaixo de 25kb.

Otimização de CSS

  • Use css sprites;
  • Coloque os arquivos no topo do documento;
  • Evite expressões no CSS;
{background-color: expression((new Date().getHours()%2 ? “#00000” : “#FFFFF”))}
  • Use arquivos externos (evite inline e tag style);
  • Prefira <link> ao invés de @import – Utilizando <link> você pode aproveitar o paralelismo dos navegadores, com o @import não.

Carregamento modular js

Utilizamos o carregamento modular do js quando precisamos de mais performance e organização. Através do carregamento modular, podemos carregar apenas os arquivos, funções ou classes específicas que iremos usar. Para isso, podemos utilizar o Require JS.

Vantagens:

  • Carregamento otimizado, não precisamos carregar tudo;
  • Podemos carregar apenas uma função ou classe;
  • Integrado com NodeJs;
  • Jquery incorporado;
  • UglifyJS para comprimir e unificar todos os js requeridos.

O requireJS trabalha de forma simples, apenas uma função chamada “require(“file”, function)”. O grande diferencial é que o arquivo será carregado somente quando você precisar.

require(["jquery", "jquery.alpha", "jquery.beta"], function($) {
    //the jquery.alpha.js and jquery.beta.js plugins have been loaded.
    $(function() {
        $('body').alpha().beta();
    });
});

HTML5 Boilerplate

O HTML5 boilerplate é um conjunto de boas práticas para você iniciar o seu projeto otimizado em HTML5. Com ele você tem um arquivo .htaccess totalmente configurado para trabalhar da melhor maneira possível, além disso também contamos com:

  • Suporte cross-browser;
  • Compatibilidade com browsers legados;
  • Estrutura padrão de um documento HTML5 otimizado;
  • Estrutura padrão para criação de plug-ins js;
  • Estutura padrão para css cross-browser.

Ferramentas de diagnóstico

Com as ferramentas de diagnóstico, podemos saber como está o fluxo de nossas aplicações, além de sabermos exatamente quais arquivos ou recursos estão deixando o site lento. Aqui vai uma lista dos mais populares:

  • Chrome DeveloperTools – Para debugação do js, analise de recursos e elementos;
  • WebPagetest – Executa diversas validações e testes de performance, além disso fala o que seria ideal fazer para resolver os problemas;
  • Firebug – Para debugação do js, analise de recursos e elementos;
  • GzipTest – Verifica se determinado domínio usa compressão GZIP;
  • HTTP Analysis Tools – Diversas ferramentas de analise, como compressão, cache, invalid caches;
  • Page Speed – Verifica se sua aplicação segue as diretrizes de um site otimizado.

Conclusão

Eessas são algumas das estratégias utilizadas para otimizarmos nossas aplicações e todas estão disponíveis com mais detalhes no yahoo developers. Caso alguém conheça outras estratégias, por favor compartilhe conosco nos comentários. A intenção desse artigo é divulgar boas práticas!