Saudações!
O grande problema de todas as criaturas que fazem artigos sempre é tempo. Meu tempo se divide ultimamente em cozinhar e trabalhar, então os artigos no blog tem ficado escassos. Hoje vamos mais uma vez tentar mudar isso.
Cenário
Imagine a seguinte situação:
Seu site, com tudo funcional, em seu perfeito e equilibrado estado, precisa de uma alteração, um novo recurso, ou algo parecido. Para isso, você tem que alterar o seu CSS e seu Javascript. Até ai tudo bem, nada de mais, visto que é algo banal, alterações são banais (NOT!), mas alguns usuários assiduos não estão vendo essas alterações feitas no sistema. O que diabos está ocorrendo? Se chama cache.
Cache
Para os pouco iluminados, cache é mais ou menos como copiar uma música no teu computador para evitar de sempre ter que ir na prateleira buscar, mas aplicado a informática. No caso do CSS e do Javascript, ele guarda uma cópia desses arquivos na máquina do cliente. Quando esse cliente acessar o site novamente, ao invés de fazer o download do arquivo do site, ele usará o arquivo em cache, evitando consumo de banda para o cliente e para o site. Essa cópia tem uma data para expirar, mas em muitos casos, não podemos contar com todo esse tempo (e sorte).
Evitando o Cache
Agora que já sabemos o que é Cache e como nosso browser usa ele, vamos aplicar isso no nosso cenário inicial. A prática padrão para isso é concatenar na URL do CSS/JS uma string, vamos iniciar com uma declaração padrão de um CSS (pode ser um JS, mas vou usar CSS para os testes):
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
Bom, se analisarmos usando alguma ferramenta (neste caso, o firebug), vamos ver que no primeiro acesso, ele faz o download do CSS, tudo normal, mas ao acessarmos pela segunda vez a mesma página, ele não faz novamente o download do CSS e sim carrega ele do cache. Hum, já era sabido que isso ia acontecer, mas dessa vez, vamos fazer com que ele recarregue o CSS, sem necessidade de limpar o cache:
<link rel="stylesheet" type="text/css" media="screen" href="main.css?nocache" />
Hey! Mas o CSS aceita parâmetros como PHP?
Não, não aceita, nem cogite deixar esse tipo de pensamento alocado no cérebro. Ele não aceita parâmetros, mas ele aceita a adição de conteudo "como se fosse" um parâmetro.
Recarregamos a página e analisamos novamente. Que maravilha, ele fez novamente o download do CSS como queriamos! But wait! se fizermos isso mais uma vez, lá vem o cache novamente para atrapalhar.
Isso acontece porque ao adicionarmos a string, ele vai procurar no cache um arquivo "main.css?cache" para o seu dominio e não vai encontrar, porque em cache estava o "main.css", mas na segunda vez, ele vai encontrar e usar o cache novamente.
E agora? Eu quero que ele recarregue o CSS sempre que o usuário acessar o site. Como vamos fazer isso?
Aqui entra nosso amigo PHP para nos dar uma mão (poderia ser em qualquer linguagem decente de programação). O que vamos fazer é adicionar como "parâmetro" ao CSS um timestamp (da execução do script), usando a função time do PHP assim:
<link rel="stylesheet" type="text/css" media="screen" href="main.css?<?php echo time();?>" />
Dessa maneira, sempre que o o usuário acessar o site, ele vai recarregar o CSS e sempre ter a última versão.
Isso funciona, na maioria dos casos vai ser o suficiente, mas imaginem um site com milhares de acessos, cada usuário tendo que recarregar sempre o CSS/JS, o consumo de banda que isso geraria no servidor. That's not cool!
Evitando o Cache (menos nocivo)
Existe uma maneira menos nociva de evitar o cache, que é recarregar o CSS/JS somente quando ele tiver alguma alteração, mantendo o cache até quando for necessário recarregá-lo.
Para isso, precisamos descobrir a data de alteração do arquivo (lá vem o PHP de novo) e usarmos ele como "parâmetro":
<link rel="stylesheet" type="text/css" media="screen" href="main.css?<?php echo filemtime('main.css'); ?> />
Agora sim, ao invés de recarregar o CSS toda santa vez que o usuário acessar o site, isso é seletivo, somente quando há uma mudança no CSS, mudando o timestamp de alteração do arquivo, ele será recarregado, consumindo somente a banda necessária, no momento certo!
Não foi tão dificil assim, podem admitir :)
Ficamos por aqui, aguardem notícias!
Sem Posts Relacionados.

Eai Henrique,
contribuindo com o problema:
a melhor solução neste caso, é trabalhar com etags (http://en.wikipedia.org/wiki/HTTP_ETag)
Por sinal, precisamos fazer isso naquele sistema que sabemos bem.
Olá, valeu pelo post, vem cá o não adianta pra nada ? vo fazer uns testes…
O que exatamente não adianta?
A ideia é otima e rapida mas como todos os programadores tem o certo problema, chamdo Internet Explorer. Não Funfou. Parabens mesmo assim
Não testei em versões mais recentes do IE, em qual que tu tentaste e não resolveu?
Pessoal, boa tarde!
Henrique, bom artigo e boa iniciativa. É uma situação que venho tendo aqui no Goldmap, mas sua solução ainda não cobre todo o problema.
Dê uma olhada nesses links que creio que pode ajudar na discussão.
1) (Para o lucas stephanou no primeiro comentário) Esses mostram que Etags nem sempre são a melhor solução: http://www.mnot.net/blog/2007/08/07/etags e http://html5boilerplate.com/docs/htaccess/ (procure por ETag no texto)
2) (O problema da sua solução Henrique) Esse aqui diz o pq de NÃO usar querystring para otimizar o cache: http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/
3) E esse apresenta a solução mais robusta que encontrei até então: http://particletree.com/notebook/automatically-version-your-css-and-javascript-files/
O que acham? Alguma ideia melhor?
Um abraço.
Renato Martins.
Buenas Renato!
Ultimamente eu venho utilizando a solução proposta no 3º link, adicionar um versionamento(timestamp) ao arquivo CSS e usando uma RewriteRule para ser acessado corretamente, eu vou escrever mais um post falando sobre essa “nova” solução, que pelo menos até o momento, parece ser a com menos falhas.
Muito obrigado pelo comentário e por compartilhar os links