No site que eu estou fazendo agora, que está em pré-alpha (se é que isso existe) , uma requisição simples, sem nada no cache demorava horrores. E isso porque só tem uma imagem no leiaute até agora.
Eu tinha que fazer alguma coisa. E uma regra importante sobre otimização é medir a performance antes de sequer relar no código, para ver o que (e se) você precisa fazer.
Resolvi dar um pouco de atenção para o YSlow, e ao rodar ele, ele me mostrou algo um tanto quanto vergonhoso:
- 12 http requests (9 JavaScript files, 3 StyleSheets)
- Load time: 13.23s (server in other country)
- 262KB to load
E uma bela de uma nota F no YSlow.
Se, por um lado, o Rails vem com tudo pronto e fácil para você, por outro ele pode ser um tanto quanto lerdo se você não souber tunar a aplicação. Prototype, script.aculo.us e afins estão a um include de distância, mas eles vem preparados para você desenvolvedor, e não para você usuário.
Ganha-se muito tempo, tanto de desenvolvimento quanto em performance, resolvendo primeiro os problemas de carregamento da página, e depois a sua lógica. Isso significa que: quanto menos arquivos externos, e quanto mais comprimidos eles estiverem, melhor.
O legal é que o Rails tem uma solução simples para isso: passar o parâmetro :cache => true para os métodos javascript_include_tag e stylesheet_include_tag. Ele faz com que todos os arquivos sejam fundidos em um só, all.js, ou all.css. Isso deu o seguinte resultado:
- 3 http requests (2 Javascript files (um é o widget do uservoice), 1 StyleSheet)
- Load time: 4.04ms (server in other country)
- 143KB to load
Bem melhor! Mas ainda dá pra melhorar. Se você configurar o seu servidor da maneira certa, ele usa gzip para mandar uma versão compactada da página e dos arquivos externos. Eu já tinha instalado o módulo no Nginx, mas mudei o servidor para Apache 2, e acabei esquecendo.
A dica aqui é que se você procurar na internet sobre como configurar o Apache para usar gzip, você vai dar de cara com um monte de links para o mod_gzip, módulo externo ao Apache. Mas você não precisa dele: basta ativar o mod_deflate, que é nativo e vem instalado em praticamente todo Apache. É só procurar por ele em /etc/apache2/mods-available/. Edite o arquivo /etc/apache2/apache2.conf, adicionando:
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml application/xhtml+xml text/javascript text/css application/x-javascript
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
DeflateCompressionLevel 9
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
</IfModule>
Rode:
sudo a2enmod deflate
sudo /etc/init.d/apache2 stop
sudo /etc/init.d/apache2 start
e pronto! Os resultados para mim foram:
- 3 http requests (não mudou em relação ao teste anterior)
- Load time: 2.99s (server in other country)
- 42.2KB to load
E ainda tem mais! Se você for um dos 20 primeiros a comentar, receberá… Você pode ativar outro módulo do Apache, o mod_expires, e configurar imagens e arquivos externos para expirarem daqui a muito tempo. Assim o browser nem tenta pegar os arquivos que já tem. Abra novamente o arquivo /etc/apache2/apache2.conf,e coloque:
<IfModule mod_expires.c>
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
ExpiresActive On
ExpiresDefault "access plus 1 year"
</FilesMatch>
</IfModule>
Rode:
sudo a2enmod deflate
sudo /etc/init.d/apache2 stop
sudo /etc/init.d/apache2 start
Isso fez com que as requisições seguintes carreguem em 0,7 segundos, ou até menos! E agora a aplicação recebe nota B no YSlow!
A lição de tudo isso: Otimização prematura é a raiz de todo mal. Ainda há espaço para mais: Colocar as versões minimizadas do Prototype & afins, mas para um único post já está de bom tamanho.