Optimização de websites ao nível do front-end

Uma interacção eficaz entre o utilizador e um determinado website está dependente de aspectos gráficos ao nível do design e usabilidade das páginas mas também fortemente condicionada pelo facto do website conseguir responder rapidamente às acções do utilizador. É sobre este último aspecto da melhoria do tempo de resposta de aplicações de Internet que este artigo se debruça.

A maior parte das optimizações normalmente efectuadas a websites é feita nos processos de geração do documento HTML, traduzindo-se maioritariamente por ajustes e melhorias ao nível de servidores web e sistemas de gestão de bases de dados. Contudo é de realçar que as optimizações a esse nível apenas vão incidir em cerca de 20% do tempo total de resposta do documento até que este chegue ao utilizador. É pois facilmente compreensível que é de extrema importância optimizar os outros 80% do tempo de resposta, é aqui que surge o conceito de front-end optimization associado a páginas de Internet. Neste artigo estão descritas 20 boas práticas que devem ser tidas em conta de forma a efectuar-se correctamente este tipo de optimizações.

Esta lista não tem a pretensão de enumerar todas as boas práticas que devem ser seguidas no desenvolvimento de um site de Internet, pretende apenas chamar a atenção para algumas delas cabendo ao leitor deste documento ter a devida precaução quanto a outros aspectos que poderão eventualmente ser relevantes. As primeiras 14 boas práticas foram retiradas do livro do Steve Souders com o título de High Performance Web Sites.

1 – Fazer menos HTTP requests

Apenas entre 10% a 20% do tempo de resposta de uma página de Internet é gasto na resposta do ficheiro HTML sendo os restantes 80% a 90% gastos em HTTP requests de todos os componentes da página (imagens, scripts, folhas-de-estilo, Flash…) que se encontram referenciadas no documento HTML. Assim este é provavelmente o aspecto que caso seja correctamente optimizado irá causar maiores melhorias no desempenho de uma determinada página de Internet. A remoção de componentes da página iria proporcionar uma melhoria automática no desempenho, contudo também iria comprometer o design final da página. O ideal é manter o design desejado e ao mesmo tempo diminuir o número de HTTP requests, para isso podem-se seguir um conjunto de simples técnicas que conseguem melhorar o tempo de resposta de algumas páginas para metade ou até menos.

A ideia principal por detrás dessas técnicas passa por a fusão de conteúdos de forma a que um elevado número de HTTP requests possa ser transformado num número mais reduzido. Para imagens existem variadas técnicas que permitem essa união, nomeadamente: Image Maps ou CSS Sprites, de seguida encontram-se dois pequenos exemplos destes mecanismos. Existe também para imagens uma técnica que permite eliminar os pedidos de HTTP dessas mesmas imagens denominado de Inline Images, ainda que este método não se encontra disponível na versão actual de alguns browsers incluindo o Internet Explorer. Relativamente a outros ficheiros que não sejam imagens o principio a aplicar deverá ser o mesmo, e sendo assim ficheiros como folhas-de-estilo ou JavaScripts devem na medida do possível serem fundidos num menor número.

Image Maps

Image Maps – Server side – Não aconselhável


Utilizador envia as coordenadas do clique: http://…/navbar.cgi?127,13.

Image Maps – Client side – Recomendável

O mecanismo de Image Map do lado do cliente é preferível essencialmente por permitir ser utilizado independentemente da localização do rato estar ou não numa determinada zona.



  

CSS Sprites

Atenção: Não é suportado em alguns browsers mais antigos como é o caso do Opera 6!



2- Usar uma Content Delivery Network

As Content Delivery Networks conseguem fornecer um factor de proximidade bastante apetecível do utilizador final, conseguindo-se tempos de resposta melhorados. Além disso as CDN permitem servir como cópias-de-segurança, aumentar a capacidade de storage, permitir mecanismos de caching mais precisos e absorver picos de tráfego.
Maioritariamente as CDN são utilizadas para servir conteúdos estáticos, como imagens, scripts, Flash, etc… Isto acontece porque os ficheiros estáticos têm poucas dependências. Por outro lado os conteúdos dinâmicos estão dependentes de um conjunto variado de factores como ligação a base de dados, autenticação, optimizações a nível do hardware e do Sistema Operativos entre outros aspectos.

3 – Adicionar cabeçalhos de expiração

A promoção da utilização de mecanismos de cache para conteúdos que mudam pouco frequentemente pode trazer significativas melhorias. Para o conseguir pode-se fazer uso dos mecanismos de header expires e max-age. Em conteúdos que mudam mais frequentemente também se podem utilizar estes mecanismos mas com o cuidado de usar tempos de cache mais reduzidos ou então mudar o nome do ficheiro a ser alterado (por exemplo recorrendo à numeração numérica de versões do ficheiro) . Como é compreensível estes mecanismos só trazem melhorias quando a cache do utilizador se encontra preenchida pelo que da primeira vez que ele visita a página as melhorias são inexistentes.

4 – Compressão G-Zip

Reduzir o tempo da resposta HTTP pode ser alcançado reduzindo o tamanho dessa mesma resposta, uma vez que assim o tempo de transferência diminui visto que menos pacotes de informação têm de ser transferidos para o utilizador.
Como a maior parte dos browsers suportam esta forma de compressão de resposta HTTP é aconselhável instalar os módulos nos servidores web e activar este mecanismo em todos os tipos de ficheiros que se encontram no servidor, não esquecendo os scripts e folhas-de-estilo.

Num servidor Apache 1.3 deve-se utilizar o mod_gzip, já num servidor Apache 2.x deve ser usado o mod_deflate.

5 – Colocar as folhas-de-estilo no topo

Ao colocar as folhas-de-estilo no topo do documento HTML permite com que a página seja reenderizada de forma progressiva. Assim o utilizador não fica perante uma simples página em branco durante um elevado período de tempo, o que caso acontecesse poderia fazer com que o utilizador ficasse impaciente e saísse da página. Com a folha-de-estilo no topo o browser consegue ler o estilo da página inicialmente e ir mostrando correctamente os vários componentes à medida que os vai recebendo. A colocação da folha-de-estilo no fundo impede o browser de mostrar os conteúdos sem que a folha-de-estilo tenha sido completamente descarregada.

6 – Colocar os JavaScripts externos no fundo

Relativamente aos JavaScripts a regra é a oposta à das folhas-de-estilo, devendo neste caso serem colocados no fundo do documento HTML. Tal regra é recomendada porque o download destes scripts bloqueia o paralelismo que se processa ao nível do download dos outros vários componentes da página. Ficando o mecanismo de reenderização progressivo da página fortemente prejudicada quando a ligação para estes scripts se encontra no topo da página.

7 – Evitar as expressions do CSS

Devem ser evitadas ao máximo expressions do CSS uma vez que estas expressões são analisadas não apenas quando a página é carregada mas também com bastante frequência noutras situações, inclusivamente quando se faz scroll na página ou se move o rato. Esta análise constante destas expressões causa um overhead que provoca uma degradação do desempenho na visualização das páginas de Internet.

Assim deve-se fazer um esforço para evitar expressões deste tipo:

width: expression( 
  document.body.clientWidth < 600 ? 
  “600px” : “auto” );

8 – Utilizar o Javascript e o CSS em ficheiros externos

Geralmente sempre que possível deverá optar-se pela utilização de ficheiros Javascript e CSS externos por forma a promover a utilização da memoria cache, uma vez que normalmente estes ficheiros são utilizados em diversas páginas ao longo do mesmo site de Internet. Apesar de se estar a aumentar o número de pedidos HTTP (a ir contra a regra número 1 da redução dos pedidos HTTP) normalmente a utilização de ficheiros externos nesta situação é compensatória.

Deve ser sempre usada a directiva LINK em vez de ser usada a directiva @import, para efectuar a importação do ficheiro CSS.

9 – Reduzir os DNS lookups

A Internet está fortemente dependente do conceito de DNS lookups onde o nome de um determinado site é convertido para uma sequência numérica, designada por IP, que define qual a máquina onde está alojada a página. Esta conversão acarreta um custo temporal ainda considerável, tipicamente entre os 20 e os 120 milissegundos. Sabendo que o browser não consegue descarregar nada sem que o DNS lookup tenha sido efectuado facilmente se percebe que por cada DNS lookup se está a impor um travão à reenderização progressiva da página. Assim e na medida em que for possível deve-se procurar reduzir ao máximo o número de DNS lookups.

10 – Minificar o Javascript

A minificação é um conceito que traduz a tentativa de redução do tamanho dos ficheiros através da remoção de espaços e outros caracteres desnecessários, permitindo assim a optimização do seu tempo de carregamento. Neste caso em particular permite uma melhoria do tempo de resposta uma vez que o tamanho do ficheiro Javascript se torna mais pequeno. As melhorias do tempo de resposta são tipicamente entre 15% e 30% quando se utiliza este método.

Um compressor gratuito e on-line: http://www.minifyjavascript.com.

11 – Evitar Reendereçamento

Um reendereçamento é usado para encaminhar um utilizador de um determinado URL para outro URL distinto. Existem variadíssimas situações em que os reendereçamentos são utilizados, nomeadamente website redesign, controlo de fluxo de tráfego ou tradução em URLS mais facilmente memorizáveis.
Acontece que muitas vezes o reendereçamento é utilizado para carregar alguns componentes dentro de um documento HTML. Facilmente se percebe que até que o reendereçamento esteja completo nada relativo a esse componente poderá ser descarregado. Esta situação é muito utilizada em mecanismos publicitários dentro de páginas de Internet.
Assim devem ser usados os mecanismos de reendereçamento com especial cuidado e devem ser evitados ao máximo.

12 – Remover scripts duplicados

Existem muitas situações, por estranho que possa parecer, onde na mesma página é carregado o mesmo script por mais do que uma vez. Isto acontece tipicamente porque os websites são construídos por grandes e diferentes equipas onde os mecanismos de sincronização entre elas por vezes não funcionam da melhor forma.
Esta situação acarreta pedidos HTTP desnecessários para o caso do Internet Explorer se os scripts não estiverem em cache. Assim como execução de Javascript desnecessária e redundante em todos o browsers actuais. É pois perceptível que esta situação causa um overhead desnecessário.

13 – Configurar Entity tags (ETags)

Como já foi expresso a redução do número de pedidos de HTTP é o factor que melhor permite acelerar a experiência de utilização para o utilizador. Ao maximizar a capacidade do browser para colocar em cache componentes está-se automaticamente a reduzir o número de pedidos de HTTP. A maximização dessa capacidade é uma das características das ETags uma vez que permite validar se um componente em cache é válido ou não.
Ainda assim este mecanismo deve ser utilizado com cuidados redobrados uma vez que não funciona caso exista alteração do servidor a utilizar. Alem disso a não utilização deste mecanismo permite obter cabeçalhos de resposta HTTP mais pequenos.
Em situações convencionais é aconselhável desligar este mecanismo. No Apache este sistema pode ser desligado adicionando FileETag none ao ficheiro de configuração do Apache. Para desligar no IIS deve consultar o seguinte link.

14 – Permitir a permanência em cache do Ajax

Com o surgimento do conceito de Web 2.0 os websites para além de ganharem uma dimensão mais social também sofreram grandes alterações ao nível dos interfaces e da agregação de informação através de diferentes serviços web. De facto as páginas de Internet tornaram-se mais em aplicações com os conceitos de input e output bem definidos. O DHTML e o Ajax vieram facilitar a implementação desse novo paradigma.
Apesar do Ajax ser uma tecnologia que permite que os pedidos sejam feitos num formato assíncrono, o utilizador pode acabar na mesma por ficar à espera da resposta. É verdade que graças ao Ajax os utilizadores não são forçados a efectuar um reload à página e que o interface continua a responder mesmo quando o utilizador está à espera. Ainda assim o utilizador pode (e continua muitas vezes) ter de ficar à espera que os resultados sejam mostrados antes de tomar qualquer nova acção. É importante esclarecer que um evento ser assíncrono é diferente de um evento ser instantâneo.
Basicamente para melhorar o desempenho devem-se permitir entradas na cache do utilizador para os pedidos activos do Ajax, pois são estes os principais responsáveis por causar o maior impacto na experiência do utilizador. Outras das regras já apresentadas anteriormente também podem ser aplicadas ao pedidos do Ajax, entre elas estão a compressão GZip, a redução dos DNS lookups ou a minificação dos Javascripts.

Bónus - 15 – Promover download ficheiros Javascript em paralelo

Nota: Este mecanismo de paralelismo deve ser usado com precaução, uma vez que se a página a ser carregada necessite de código de um dos ficheiros que seja carregado paralelamente e se esse ficheiro ainda não tiver sido totalmente descarregado irão ocorrer problemas.

É possível descarregar ficheiros Javascript em paralelo, tirando partido da cada vez mais vulgar banda larga e da sua tipicamente elevada velocidade de acesso à Internet. Seguem-se dois pequenos excertos de código HTML que mostra como o fazer.

Sem paralelismo:

(...)


(...)

Com paralelismo:

(...)

(...)

Bónus - 16 – Utilizar favicon.ico pequeno e armazenável em cache

O favicon.ico é uma pequena imagem que tipicamente é apresentada na barra onde se encontra o endereço do site em que o utilizador se encontra. Mesmo que opte por não utilizar favicon.ico no desenvolvimento da sua página o browser vai sempre realizar um request à sua procura. Caso o icon não esteja presente o resultado devolvido pelo servidor irá ser um 404 Not Found e não aparecerá nenhum icon ao utilizador.
Como o custo associado ao request do icon não pode ser evitado é recomendável que faça proveito desta oportunidade e coloque um icon com um tamanho reduzido de forma a reforçar a identidade da sua página. Tipicamente o tamanho do icon não deverá ultrapassar 1kbyte por forma a não prejudicar o desempenho. É ainda possível definir o parâmetro expires com um valor elevado, por exemplo na ordem dos 4 meses, de forma a esse icon permanecer na cache dos utilizadores.

Bónus - 17 – Não redimensionar imagens em HTML

Ao diminuir o tamanho de imagens recorrendo a código em HTML está-se a exigir o download de um ficheiro de maior tamanho do que aquele que será efectivamente visualizado. Como é facilmente perceptível esta situação acarreta um overhead desnecessário, sendo que as reduções de tamanho das imagens devem sempre ser realizadas no próprio ficheiro da imagem.

Bónus - 18 – Utilizar o formato de ficheiro de imagens correcto

Existem diversos formatos com que as imagens podem ser guardados, uma escolha adequada desse mesmo formato pode fazer com que essa imagem se torne mais leve, ocupando menos espaço, sem que exista perda perceptível da sua qualidade para o utilizador.

Bónus - 19 – Declarar sempre as dimensões das imagens

Deve-se sempre declarar a altura e o comprimento dos diferentes componentes como imagens ou vídeos uma vez que isso evita que o browser tenha que “adivinhar” o tamanho desses objectos fazendo com que o carregamento da página demore mais. Além disso assim o browser ao reservar automaticamente o respectivo espaço para esses componentes faz com que o carregamento da página seja muito mais consistente.

Bónus - 20 – Codificar as folhas-de-estilo mais pequenas possíveis

É possível codificar as folhas-de-estilo recorrendo a código mais sucinto sem que isso traga alterações ao resultado final. Deixo alguns exemplos.

Exemplo 1:

O código:

#div_xpto {
  padding-top:15px;
  padding-bottom:10px;
  padding-left:13px;
  padding-right:0px;
}

produz exactamente o mesmo resultado do que:

#div_xpto {padding: 15px 0 10px 13px;}

Exemplo 2:

O código:

div {
  background-image:url("fundo.jpg");
  background-color:#ffffff;
  background-repeat:repeat-x;
  background-position:top center;
}

produz exactamente o mesmo resultado do que:

div {
  background:url("fundo.jpg") #fff top center repeat-x;
}

Também é recomendável comprimir o código CSS, tal poderá ser feito neste compressor gratuito e on-line: http://www.cssdrive.com/index.php/main/csscompressor.

Para um estudo mais aprofundado sobre todo este tema recomendo vivamente a leitura do livro onde fui buscar inspiração para este artigo. Como referi inicialmente estas são apenas algumas das boas práticas que devem ser seguidas para optimização de websites ao nível do seu front-end, se tiverem mais algumas partilhem comentando este artigo.

  1. Antonio Campos 26 December 2009 22:40:59

    Este vai para os favoritos!
    Obrigado pelo trabalho!!!!

  2. Links 27-12-09. | WebVicio.com 28 December 2009 00:05:02

    [...] O Gonçalo Rodrigues do GoncaloRodrigues.com explica como fazer optimização de sites ao nível do front-end. [...]

  3. Jorge Sepúlveda 28 December 2009 11:10:54

    Bom dia.

    Queria dar-te os parabéns pelo artigo, está excelente! Vou aproveitar a dica e vou também encomendar o livro para uma leitura mais aprofundada do tema, uma vez que me interessa bastante a nível profissional.

    Já agora aproveito para divulgar que o autor, Steve Souders, tem um outro livro sobre o tema: o “Even Faster Web Sites”. Vou ler primeiro o que recomendaste e depois logo vejo se compro o outro o não.

    Obrigado pelas dicas.
    Cumprimentos, Jorge Sepúlveda.

  4. Tomate Suicida 28 December 2009 20:06:32

    Olá,

    Bom artigo, gostei de ler e já fiz umas pequenas alterações no meu site.

    Cumprimentos

  5. Gonçalo Rodrigues 29 December 2009 11:43:06

    Fico contente por terem gostado do artigo.

    Espero conseguir continuar a escrever sobre assuntos do vosso interesse.

  6. Diego 26 January 2010 18:57:16

    Você apenas informou o que o yahoo nos informou em: http://developer.yahoo.com/performance/rules.html

    Falta informar em como realizar essas coisas.
    Como colocar css e javascript como arquivos externos?

  7. Gonçalo Rodrigues 26 January 2010 20:32:03

    @Diego:

    Relativamente ao ficheiro css externo, caso ele se chame style.css, poderás colocá-lo introduzindo no meio da secção

     ... 

    do teu ficheiro html o seguinte código:

    Quanto ao javascript, caso o ficheiro se chame Script1.js, poderás usar o pedaço de código que refiro no artigo:

  8. Diego 27 January 2010 18:19:51

    Então no caso do CMS WordPress a maioria dos CSS e JavaScript estão externos não é? Bastando somente compactá-los e uni-los, é isso?

  9. Gonçalo Rodrigues 27 January 2010 18:26:46

    @Diego: Sim, em principio estão externos. Ao compactares e ao unires esses ficheiros CSS e JavaScript estarás a optimizar esse site ao nível do seu front-end.