As 7 práticas para um site otimizado
Postado em 29. jul, 2010 por Sérgio Lopes em Web Design
Todo mundo gosta de sites rápidos. Seus primos não sabem dizer se você tem um arquitetura escalável, se seu banco NoSQL é mais robusto ou se é melhor usar Web Services SOAP ou REST. Mas eles sabem dizer duas informações com precisão: se seu site é bonito e se ele é rápido. Performance, medida pelo usuário, é o que te diz se a velocidade de resposta da sua aplicação é aceitável. E, assim como usuários não se cansam de bordas redondas e sombrinhas bonitas, sempre haverá otimizações possíveis para tornar seu site mais rápido.
[Update] Interessado em Otimizações Web na prática com truques do básico ao avançado? Confira o novo curso online de otimizações da Caelum!
Inspirado pela recente edição 2010 da Velocity Conference organizada pela O’Reilly e por uma palestra recente que dei com o Alberto Souza aqui na Caelum, além de discussões que aparecem no nosso curso que trata de HTML, CSS e Javascript, selecionei um punhado de dicas para deixar qualquer site ou aplicação Web mais rápido em instantes. Meu TOP 7 não pretende ser uma lista completa e nem detalhada de boas práticas. É mais um guia rápido sobre tudo o que você deveria fazer em qualquer site antes de perguntar a opinião dos seus primos – ou do seu chefe, ou de qualquer usuário. Eis então:

TOP 7 das Otimizações na Web:
0. Habilite GZIP em todas as suas páginas. Se você ainda não fez isso, pare imediatamente de ler esse post e faça. É o passo zero, nem vou contá-lo. Dicas de como fazer no Tomcat, Jetty, Apache, IIS.
1. Agrupe arquivos JavaScript/CSS. 90% do trabalho de otimização consiste em diminuir o número de requests feito na página e o peso de cada um deles. Você usa JQuery (ou qualquer outro framework) com JQuery UI e mais meia dúzia de plugins, sem contar o código JS da sua aplicação? Junte tudo no menor número de arquivos possíveis para evitar muitos requests. Mesma coisa com CSS, um arquivo com tudo basta. Mas gosta de manter as coisas organizadas ao invés de escrever um arquivo com milhares de linhas? Então junte essas coisas dinamicamente como faz o pessoal do Digg ou faça o serviço no build da aplicação como preferimos aqui na Caelum.
2. Comprima o JavaScript/CSS. Você escreve JS/CSS elegante, bem documentado, com código organizado e variáveis de nomes legíveis. Mas seus primos não se importa com isso, eles querem um site rápido e isso significa não trafegar no request bytes e mais bytes de documentação ou de código legível. Comprima todo o seu código JavaScript e CSS usando o YUI Compressor ou o Google Closure Compiler. Faça isso em build time ou dinamicamente.
3. Otimize suas imagens com Smush-it. Nem todos os KB de suas imagens são necessários para o cliente. Arquivos JPEG possuem uma série de metadados e PNGs possuem palhetas de cores. Remova vários KBs desnecessários de suas imagens usando o Yahoo Smush-it em todas elas.
4. Coloque CSS no topo e JavaScript embaixo. Simples assim. Referencie os seus CSS no <head> com <link> para evitar o flash effect, e coloque seus scripts logo antes do fechamento do <body> para não atrasar a renderização da tela.
5. Não redimensione imagens no HTML. Não use os atributos width e height das imagens para redimensionar seu tamanho. Sirva as imagens já com tamanho certo e otimizadas. Mas coloque sempre o width e height de todas as imagens para ajudar o browser nos cálculos da renderização da página.
6. Configure o Expires corretamente. Use o cache do navegador para prover uma melhor experiência ao usuário no segundo request – seja no retorno ao site ou navegando para a próxima página. Permita também que Proxies entre seu servidor e o cliente cacheiem elementos do seu site para evitar um download demorado. Configure o header de Expires de todo seu conteúdo estático (JS, CSS, imagens) com alguns dias de duração.
7. Use YSlow e PageSpeed. Depois que você fez todas as otimizações anteriores, instale o YSlow e o PageSpeed para um diagnóstico detalhado de seu site. Monitore sua performance constantemente e vá implementando sempre novas otimizações. Seus usuários agradecem.
Esse TOP 7 são todas as otimizações que você deveria ter feito ontem em qualquer site seu antes de começar a falar em performance. Há muitas outras práticas, algumas mais complicadas, como CSS Sprites, usar CDNs, otimizar seus cookies, fazer preload e postload de conteúdo, ou comprimir seu HTML. Dependendo da tecnologia que você usa no seu sistema, você terá maior ou menor facilidade de aplicar todas essas práticas: no JSF e ASP.NET você terá benefícios para desenhar sua interface, mas muito mais trabalho de fazer esse ajuste fino; com Struts, Rails, ASP.NET MVC, VRaptor e frameworks action based, será o contrário.
Bônus: Onde ir depois?
- Práticas de performance do pessoal do Yahoo YSlow
- Boas práticas do pessoal do Google PageSpeed
- Slides e vídeos das palestras do Velocity 2010 com o que há de mais novo em discussão
E você, que outras práticas aplica no seu website?
[Update] Interessado em Otimizações Web na prática com truques do básico ao avançado? Confira o novo curso online de otimizações da Caelum!
Sérgio Lopes
Mais sobre o autor
54 Respostas para “As 7 práticas para um site otimizado”
Trackbacks/Pingbacks
-
-
agosto 4, 2010
[...] As 7 práticas para um site otimizado blog.caelum.com.br (tags: webdesign css javascript) [...]
-
-
agosto 9, 2010
[...] aplicação em diferentes situações e identificar possíveis pontos de falha, cogite problemas de performance na aplicação, antes de blasfemar contra o servidor. Assim como no alpinismo, escalar montanhas sem [...]
-
-
dezembro 21, 2010
[...] As 7 práticas para um site otimizadopor Sérgio Lopes, em 29/07 [...]
-
-
janeiro 3, 2011
[...] http://blog.caelum.com.br/top-7-praticas-para-um-site-otimizado/ [...]
-
-
abril 28, 2011
[...] bitolados por otimizações Web aqui na Caelum então muitas otimizações já estavam integradas ao Site. A primeira versão, logo [...]
-
-
setembro 12, 2011
[...] Há muito tempo que falo que habilitar o GZIP no servidor é o primeiro passo. Não leva mais de 30s para ser feito e é suportado em todos os navegadores e servidores dos últimos 15 anos. Com ele, todo conteúdo textual (HTML, CSS, JS etc) é comprimido antes de ser enviado para o cliente, chegando a cortar mais de 50% do tráfego total. [...]
-
-
março 28, 2012
[...] As 7 práticas para um site otimizado | blog.caelum.com.br [...]
ASSINE NOSSO RSS
Paulo Silveira
29. jul, 2010
é um post excelente.
vejo que muitas empresas fazem a escolha errada entre component based e action based para seus websites, tendo um prejuizo enorme de SEO e performance, por causa da dificuldade do fine tuning do html/javascript depois de pronto. é precisa conhecer bem os tradeoffs.
Maurício Linhares
29. jul, 2010
Component based é sempre um problema quando você quer fazer esse tipo de otimização.
Mas um detalhe, se você já está com GZIP habilitado, não vale a pena fazer o “Comprima o JavaScript/CSS”. O ganho é marginal e não vale o trabalho.
Leandro
29. jul, 2010
ótimas dicas! é um post bem interessante muitos nem imaginavam que existiam tais “recursos” !
Vinicius
29. jul, 2010
Não entendi o lance do png, achei que ter a paleta fosse algo que fizesse o arquivo ficar menor, afinal com paleta você pode indexar as cores usando 8 bits ao invés de 24…
Hugo Roque
29. jul, 2010
Putz, muito bom, muita coisa aew eu não sabia xD
Com certeza eu vou usar essas dicas =D
Sérgio Lopes
29. jul, 2010
Pessoal, obrigado pelos comentários!
@Paulo
O fato é que component-based não é feito para WebSites e sim para WebApps. Usar JSF em um WebSite é a pior coisa que alguém pode fazer
@Maurício
Discordo que o ganho da minificação seja marginal. Pegue o JQuery, por exemplo, que muita gente usa. O não-minificado e gzipado fica com 46.1k. O minificado e gzipado fica com 24.6k, quase 50% de ganho. E, sinceramente, o trabalho de minificar é ridiculamente fácil: um scriptzinho no seu build com 3 linhas resolve isso. Vale o trabalho sim.
@Vinicius
Se você já se preocupa com sua palheta quando gera as imagens no Photoshop, já é metade do caminho. No post não expliquei direito mesmo, mas o Smush-it consegue, por exemplo, reduzir sua palheta sem perder qualidade. Alguns detalhes sobre o processo de smush:
http://developer.yahoo.com/performance/rules.html#opt_images
Deyvid Nascimento
29. jul, 2010
Sem palavras, ótimo artigo, dicas muito importantes como por exemplo a parte de comprimir código, e agrupar css e javascript, e as ferramentas YSlow e PageSpeed.
parabéns.
Roberto Nogueira
29. jul, 2010
@Maurício @Sergio
mas se vc habilitar o gzip não vai perder o cache? lembre-se que no request envia um ” If-Modified-Since” e no response deve voltar o código 304 para o browser saber que pode usar o item armazenado no disco do usuario.
Oras… se o servidor está sempre compactando automaticamentenão não vai ficar verificando o arquivo local foi modificado para retornar um 304. então sempre vai baixar já que nunca vai receber um aval pra usar o cache. sacaram?
Sérgio Lopes
29. jul, 2010
@Roberto
Eu não entendi a relação entre o GZIP e o If-Modified-Since. Existe cache sim de coisas GZIPadas tanto no browser quanto em alguns proxies. E o funcionamento do If-Modified-Since é o mesmo (ele verifica e devolve 304 ou 200 normalmente).
E lembrando que se você seguir a dica do Expires, nem esse request de verificacao precisa ser feito. O cache é local no browser e não precisa bater no servidor. Você pode, porem, usar o If-Modified-Since/Date-Modified (ou, melhor ainda, ETags) para conteúdo dinâmico com pouca alteração ou para reutilizar o componente mesmo depois que o Expires terminar
Roberto Nogueira
30. jul, 2010
@Sergio
Obrigado pela atenção.
a relação que me refiro é que para funcionar o recurso compactado é necessário atribuir response.setContentType(“application/x-gzip” ). Ou seja, não adianta compactar um arquivo e simplesmente colocar lá para o usuário baixar. Sendo assim, isso seria aplicado via servlet, ou seja, alguma rotima automatizada que sempre pegaria um arquivo descompactado e depois faria a compressão aplicando o respectivo header.
É aí que entra o If-Modified-Since. Por exemplo, se fosse uma requisição de imagem por padrão o proprio servidor http iria validar a data de modificação com base no sistema de arquivos. Agora se eu coloco um servlet que gera ou manipula as imagens estaria pegando outro caminho e teria que fazer essa validação com minhas próprias mãos.
Portanto, quando uma pessoa coloca um servlet que compacta o js com gzip e aplica o header, já perdeu a validação de cache do servidor. é isso que estava querendo dizer.
[]s,
bob
Roberto Nogueira
30. jul, 2010
@sergio
ops me enganei, ao inves de setContentType(“application/x-gzip” ) o correto é setHeader(“Content-Encoding”, “gzip”);
Sérgio Lopes
30. jul, 2010
@Roberto
Entendi agora sua questão! Recomendo dar uma olhada nos mecanismos prontos do seu servidor para fazer o GZIP. Acho que não é uma boa tentar escrever sua própria Servlet, gerar arquivos compactados na mão ou algo assim.
Todos os servidores Web possuem mecanismos para fazer tudo isso transparentemente, garantindo a integridade dos headers, Date-Modified, por exemplo. Eu uso aqui o AppEngine que me dá GZIP automático sem eu fazer nada (aliás, não é possível nem desabilitar). Quem usa Tomcat/Jetty etc diretamente tem que habilitar mas coloquei uns links aí no post que mostram como fazer.
Lucas Pereira Caixeta
01. ago, 2010
@Lucas_Caixeta
Ótimo post cara!! vou seguir as ideias!
Levy Carneiro Jr.
02. ago, 2010
Pessoal,
postei 4 vídeos no Youtube, com dicas de performance Client-Side. Confiram:
http://levycarneiro.com/2010/04/webcast-como-melhorar-a-performance-do-meu-site/
Abraços,
Levy
Tiago Allen
03. ago, 2010
Gostaria de agregar uma dica sobre otimização de css.
Entendo que quanto maior a sua estrutura de código CSS mais difícil fica de mantê-la, por mais que você tenha um css organizado ainda assim fica difícil.
A minha sugestão e fazer uso do LESS.app http://incident57.com/less/, esse aplicativo para Mac me permite escreve os arquivos em less e depois compila-los automaticamente sem que eu precise estartar um servidor Rails na minha máquina. Desta forma consigo escrever grandes linhas de código, com múltiplos arquivos e ainda padronizar uma serie de funcionalidade do código de forma inteligente e ordenada.
Hoje utilizo esse recurso tanto para grandes projetos quanto para pequenos sites de puro html, otimização na produtividade e também na hora de projetar o css.
Fabiano David
05. ago, 2010
Legal essa discussão e muito bom o Post. Vale todas as dicas
http://www.fabianodavid.com.br
http://www.aehweb.com.br
Joao Polo
06. ago, 2010
Excelente post! Me faz repensar várias coisas… como por exemplo a parte do css ser no topo (o que eu já faço) e os scripts embaixo (o que nem eu… nem quase ninguém faz).
Abraço!
Roberto
06. ago, 2010
Sensacional o post! Só não entendi como fazer o procedimento 1 que é agrupar os arquivos js e css dinamicamente ou no build da app. Alguma luz?
E parabéns pelo post. Abraço!
Sérgio Lopes
06. ago, 2010
Oi pessoal, obrigado pelos comentários!
@Roberto
A ideia é você juntar vários arquivos JS ou CSS em um só. Por exemplo, se você usa JQuery, JQuery UI, um plugin qualquer e mais o código da sua aplicação. Ao invés de deixar os 4 arquivos separados, junte seu conteúdo (um “super.js”) que você carrega de uma vez só.
Mas o ideal é não fazer essa junção na mão, misturando milhares de linhas de código diferentes, senão a manutenção fica complicada. Aí recomendo que você faça, por exemplo, uma Servlet/Filter/Action que dinamicamente lê os arquivos isolados e depois cospe uma saída única. Ou então que você faça estaticamente no build através de alguma task Ant/Maven/etc que lê os arquivos separados e junta em um só.
O pessoal do Digg (link acima, repare na URL) fez do modo dinâmico: você chama uma URL deles passando os arquivos que quer e ele junta. Na Caelum (link acima), preferimos build time e temos um arquivo caelum.package.js que inclui uns 8 arquivos diferentes durante o Ant.
Roberto
07. ago, 2010
@Sergio
Foi o que pensei em fazer: montar uma Servlet/Filter/Action pra manipular os arquivos e montar um único. Ideia simples, porém genial! E mto legal mesmo o que o Digg faz.
Agora está respondido. Mto obrigado!
Forte abraço!
Levy Carneiro Jr.
09. ago, 2010
Uma coisa importante também é criar travas no site ou aplicação, para que a nota do YSLOW e/ou PAGE SPEED tão suada de ser alcançada, se perca depois do designer subir uma imagem com o dobro do tamanho necessário
Ou seja, melhorar o processo para que o site/aplicação não perca a performance nunca
Leandro
11. ago, 2010
Muito interessante e muito útil essas dicas da Caelum sobre aotimização de sites, será de grande valia.
Vocês estão de Parabéns !
Abraço,
Leandro
Icaro
11. ago, 2010
SENSACIONAL esse post !!
Me ajudou muito, meus sites ficarão muito mais rápidos.
Forte abraço
Ícaro
Jeff
18. ago, 2010
Desculpe a ignorância mas, alguem tem algum link com material sobre como configurar o header de expires de conteúdos estáticos?!?
Sérgio Lopes
18. ago, 2010
@Jeff
Depende muito da plataforma que você está usando. No pior dos casos você cria um filtro Java que chama response.addHeader(Expires) pra você. Mas o recomendado costuma ser servir coisas estáticas em uma infra própria para isso.
Por exemplo, deixar um Apache na frente no Tomcat/JBoss/etc servindo os CSS/JS/imagens. Aí você configuraria no .htaccess dele.
No AppEngine, por exemplo, configuramos no arquivo appconfig.xml na secao static-files (sintaxe própria). Se você usar algum CDN externo, possivelmente ele já faz isso por você também.
Em suma: depende da sua infra, mas sempre há um jeito
Flavio Duarte
19. nov, 2010
Sérgio, muito bom o post
você pode falar como eu posso agrupar no build? “… faça o serviço no build da aplicação como preferimos aqui na Caelum.”
Sérgio Lopes
19. nov, 2010
@Flavio
Aqui na Caelum, temos arquivos que chamamos de *.package.js (ou CSS). Nesse arquivo de pacote a gente declara os arquivos a serem incluídos, um por linha. Por exemplo:
/javascripts/lib/jquery.js
/javascripts/lib/jquery-ui.js
/javascripts/base.js
/javascripts/outro.js
Em tempo de desenvolvimento, temos um filtro (javax.servlet.Filter) que lê dinamicamente esses arquivos package e vai incluindo os arquivos pra gente. Em produção o filtro não existe, porque no build a gente roda um script que procura os arquivos package e faz a inclusão pra gente.
Dá pra ver um desses arquivos no site da Caelum:
http://www.caelum.com.br/javascripts/caelum.package.js
(esse aí já ta minificado também, mas dá pra perceber que cada linha nova é um arquivo diferente)
Thiago Araujo
03. dez, 2010
Eu habilitei o gzip no jboss, no page speed aparece:
- Cabeçalhos de Resposta
Content-Encoding: gzip
- Cabeçalhos de Solicitação:
Accept-Encoding: gzip,deflate
Mas se eu executar o Analyze Performance aparece entre outro o Enable compression.
O que eu preciso fazer alem de habilitar no Servidor de Aplicação para utilizar o gzip?
Denis Santos
06. jan, 2011
As dicas são ótimas, parabéns!
Vejo que em projetos com arquitetos experientes isso tudo é uma realidade, mas com o passar do tempo as aplicações são esquecidas devido a novas demandas, o que acaba caindo na mão de equipes de manutenção que não adotam as mesmas práticas.
Mas, mais uma vez, parabéns pelo POST!
Natascha
07. fev, 2011
Olá, adorei o post e sua palestra sobre o assunto na PHP Conf do ano passado!
Sergio, não sei se poderia ajudar:
Na página do Yahoo a função flush() do PHP é recomendada para otimização porque vai enviando parcialmente a resposta ao navegador.
Mas, no manual do PHP, diz:
1. flush() não tem efeito no funcionamento de buffer do seu servior ou do browser do cliente.
2. Módulos de servidor para o Apache como o mod_gzip podem fazer buffer por si o que fará com que flush() não resulte em os dados serem enviados imediatamente para o cliente.
Ou seja, realmente essa recomendação do flush() será que procede?
Sérgio Lopes
07. fev, 2011
Oi Natascha, obrigado!
Sobre o flush, tenho o mesmo problema por aqui, em Java. Usar o GZIP também impede que ele tenha algum efeito. Acho que em 99% dos casos, o flush é uma regra descartável, até porque usar GZIP acaba sendo bem mais importante.
Abraços
Natascha
07. fev, 2011
Obrigada Sérgio!
1) Mais uma dúvida: configurei Expires alto. A configuração da ETag eliminaria ter que mudar o nome do arquivo para fazer uma atualização do cache?
(Coloquei no Apache diretiva “FileETag MTime”, para pegar data e hora da última modificação)
2) Meu Apache não está comprimindo GZip para arquivos javascript – adicionei:
text/javascript e application/x-javascript
Coloquei da mesma forma na Diretiva Expires e ali funcionou, só no GZip que não (pra html, css foi ok)
Grata!
Sérgio Lopes
08. fev, 2011
@Natascha
1) Não, você ainda vai ter que mudar o nome do arquivo, caso contrário o browser não tem como saber que o arquivo mudou. O ETag (assim como o Date-Modified) vai apenas impedir que o arquivo seja baixado de novo pelo browser quando acabar o tempo do Expires.
Aqui na Caelum, temos um script que coloca automaticamente o timestamp no nome do arquivo. Assim só muda quando o arquivo for alterado mesmo.
2) Humm, não sei se consigo te ajudar, não conheço muito os detalhes de configuração do Apache
Lucas Murata
22. mar, 2011
Um livro muito bom que trata destes assuntos: High Performance Web Sites: Essential Knowledge for Front-End Engineers.
Eu uso JSF em produção, mas estou prestes a desistir dele. Agente perde liberdade na View, não tem controle sobre HTML, CSS e JS, além de códigos aliens que ele gera sozinho. Sem contar com milhoes de JS que ele importa.
Sinceramente, acho que JSF é inadequado até para WebApp.
Paulo Silveira
23. mar, 2011
@Lucas, tem razao, no caso de websites onde é necessario o controle de JS e HTML, JSF te trara muito trabalho para customizar.
Se a Webapp for para intranet, rica em formularios, sem necessidade de exatidoes de html e js, pode ser uma boa escolha.
Michel Banagouro
12. abr, 2011
Ótimo post!
São dicas úteis e q eu costumo usar no meu dia-a-dia.
Até fiz um post sobre um desses itens no meu blog: compressão gzip no asp .net mvc.
http://mbanagouro.net/site/2011/04/07/compressao-gzip-no-asp-net-mvc/
Rodrigo
29. abr, 2011
Oi, estive vendo o seu post, e achei muito bom… so fiquei com uma duvida referente ao tópico 6, para a configuração do Expires corretamente, como é feita esta configuração?
Nao consegui encontrar nada, vi que geralmente o codigo do page speed pede para configurar o javascript e o css com estas informações, como faz isso ?
Sérgio Lopes
29. abr, 2011
Oi Rodrigo!
Vai depender do servidor que você está usando. No post eu linkei para tutoriais no Tomcat, Apache e IIS.
Abraços
Lucas Peperaio
04. mai, 2011
Muito boas as dicas, usei na minha ferramenta online.
valeu
Bruno
17. mai, 2011
Muito bom.
Sou iniciante em Web Design e estou me inspirando em suas dicas para ter sucesso.
Filza Azize
16. jun, 2011
Ola…
Gostei das dicas…
Gostaria de saber como redimensionar uma foto sem alterar a qualidade de imagem usando código Java..
Obrigada
Mario Santos
03. jul, 2011
Muito bom! Realmente isso faz toda a diferença na otimização dos sistemas na web.
Thyago Ferreira
12. jul, 2011
Muito bom cara, recomendações práticas e objetivas, tem coisa melhor?
Wolmir
06. out, 2011
Parabéns gostei muito das dicas, inclusive me entusiasmou muito em pesquisar mais e aprender sobre otimização de paginas….
Humberto
08. dez, 2011
Olá, quanto à compressão gzip, isso é possível no JBoss AS 7? Pelo que vi parece que essa funcionalidade foi retirada nessa última versão.
Felipe
27. mar, 2012
Ola,
Estou tentando setar o Header Expires e mesmo com o Page Speed mostrando q esta tudo OK, o browser continua chamando o arquivo no servidor.
Postei a pergunta no guj com mais detalhamento.
http://www.guj.com.br/java/268731-problema-com-cache-no-browser—cache-control-expires-last-modified-etc
Valeu a ajuda,
e parabéns pelo post!!
Felipe
28. mar, 2012
Como vcs fazem para setar a data de Expiracao/Cache-Control dos Arquivos?
Vcs fazem um filtro manualmente no java ou configuram para q o servidor faça cache?
E mais uma pergunta: Como fazer para configurar o cache pelo servidor? Eu achei esse link aqui será q ta certo?
http://www.symphonious.net/2007/06/19/caching-in-tomcat/
valeu!