Evitando caching quando (e só quando) o arquivo CSS for atualizado

Caching é uma das coisas mais interessantes e, até mesmo, importantes do protocolo HTTP. Mas quando se trata de arquivos CSS, caching pode ser um imenso problema.

Não tenho certeza, mas acho que isso se deve a algum tipo de implementação equivocada do protocolo nos user agents. Mas, o fato é que, quando você atualiza um arquivo CSS, a não ser que o usuário dê um reload (às vezes é necessário um shift + reload), o CSS que está no cache do browser será usado, ao invés da nova versão, que acabou de ser modificada. É um saco, mas há uma maneira bem simples de resolver isso.

O Élcio chamou a atenção para o fato de que, se você coloca uma query string (algo como “?alguma-coisa”) após o nome do arquivo, este é tratado pelo browser como um novo arquivo, e a versão em cache é descartada em favor de uma nova versão, que será baixada do servidor.

Uma solução é colocar uma query string diferente a cada vez que você atualizar o seu CSS. Mas isso demanda um trabalho manual de edição de um outro arquivo, a cada vez que o CSS for alterado. Portanto, não é uma solução tão boa assim, mas é a única opção disponível para páginas HTML estáticas. Seria algo mais ou menos assim:

<link rel="stylesheet" href="estilo.css?1">

Alterou o arquivo, troque o “?1″ para “?2″, e assim sucessivamente.

Mas, e quando o seu site não é formado apenas por páginas estáticas (o que é o cenário mais comum hoje em dia, com a abundância de serviços baratos de hospedagem que dão suporte a linguagens server-side, como PHP), o que fazer para automatizar esse processo?

Uma estratégia que julgo ser interessante, e que tenho usado ultimamente, é utilizar o timestamp da data e hora da última alteração do CSS na query string. Dessa forma, a versão do CSS em cache será descartada sempre quando (e somente quando) o arquivo CSS for alterado.

Se você usa wordpress, isso é bem simples de implementar. Edite no arquivo header.php (ou equivalente, caso você usa uma nomenclatura diferenciada) do seu template a linha que faz a chamada ao arquivo CSS, que pode ser assim:


<link rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>" type="text/css">

ou assim:


<style type="text/css">
  @import url(<?php bloginfo('stylesheet_url'); ?>);
</style>

Troque <?php bloginfo('stylesheet_url'); ?> por <?php bloginfo('stylesheet_url'); ?>?<?php echo filemtime(dirname(__FILE__).'/style.css'); ?>

O resultado será algo como <link rel="stylesheet" href="http://brunotorres.net/css/style.css?1152078199" type="text/css">

Pode até ser meio tosco (meio?), mas funciona que é uma beleza, e você nunca mais vai precisar se preocupar com caching dos seus arquivos CSS.

Se você entende um pouquinho de PHP e é pouquinho esperto, você pegou a idéia e pode adaptar isso para qualquer outro sistema. Na verdade, pode até fazer algo mais interessante do que o que eu fiz e mandar pra mim a sua idéia, o que acha?

26 Comentários sobre “Evitando caching quando (e só quando) o arquivo CSS for atualizado”

Faça um comentário

Grande dica Bruno.
Acabo de implementar e testar no meu Blog.
Adeus edição manual (já vai tarde!) a cada mudança na folha de estilo.
Agora vou adaptar para meu site.
Grato por divulgar.


Boa dica Bruno…sempre tenho problemas com cache….vou testar e ver como se sai.

Abraços


Dessa eu não sabia, muito boa!!!


Massa… valeu pela dica!


#5 | Daniel Luz

Olha, apesar de tudo, eu particularmente nunca tive problemas práticos com o caching. Tanto o IE quanto o Firefox pra mim sempre testaram por novas versões dos arquivos externos em tempo apropriado.

Na verdade, essa técnica traz dois problemas: o primeiro é a performance de se verificar a data de um arquivo a cada requisição de página (em pequena escala não deve ser grande coisa, mas não sei como se sairia em um site de grande tráfego).

O segundo é que, apesar do Mozilla e do IE não seguirem essa regra, o protocolo HTTP define que URLs com query strings _não_ podem ir pro cache. Usuários do Safari (não lembro de outros browsers que seguem essa especificação) vão ficar continuamente recarregando o CSS a cada page view.

No fim, então, eu particularmente prefiro continuar com as URLs simples e confiar no cache do browser mesmo…


Boa dica Bruno!!!
E Feliz Aniversario cara!! Felicidades!


Boa dica Bruno!
Eu concordo com o Daniel Luz, mas utilizaria esta sua técnica para desenvolvimento e testes no servidor…
Para o site em produção, prefiro deixar a atualização do cache no seu “tempo normal” mesmo, sou meio neurótico com a performance! :P


grande sacada ein Bruno
show mesmo, vai facilitar e muito a vida do desnvolvedor, aliás… podemos adaptar esta técnica a outras situações tb.


Caramba! Ótimo post… Que beleza!

Nunca tinha pensado em arranjar uma solução, mas é verdade… E, com certeza, utilizarei essa “implementação” no meu prótimo tema pra WordPress =)

Abraço!


Aparentemente o Ruby On Rails já adiciona o timestamp como query string nos CSS.. Preciso checar.


Muito boa dica bruno!
Eu usava algo do tipo de colocar um rand() ali, mas toda hora ele não usava cache, então era meio que disperdicio do cache ehehe

Muito bom!

Abraços


#12 | Harlley

Acho mais fácil usar uma extensão como o WebDevelop per por exemplo e desabilitar o cache quando for necessário.


Da mesma forma isso também pode (e é) utilizando para evitar caching no Ajax, no Ajax também temos esse problema…
Acho que tudo que é coisa funcional mesmo os browser não trabalha direito :p
Top!


No cache!!!


Rapazes, nem sei como agradecer. Isso vai ajudar e muito, principalmente para desenvolver e não ter que dar shift+refresh e baixar todas as imagens e tal.


Excelente dica!!! kra eu fiz uma versão para ASP.Net e postei em meu blog .. comentando seu site como fonte é claro!!

[]‘s


Bacana seu artigo amigo.
Só para relembrar é: CTRL+F5 ( e não Shift+F5 ), pelo menos aqui o shift+F5 nunca funcionou.

Mas enfim.

Outra dica, Tente justificar o texto dos seus artigos, ele iria ficar com uma estética muito mais agradável.

E isso ae!
Abração amigo.
Parabens mais uma vez.


#18 | Kasem Junior

Concordo contigo Adriano Vieira

———————————————

se o problema é ficar colocando ?1.. ?2..

tranforma ele em algo dinamico :D

tipow:

“>

aqui funfou legal ^_^


#19 | Kasem Junior

nao sabia que tinha validacao :(

ai vai o codigo:

[link rel="stylesheet" href="estilo.css?1[? php echo date("s"); ?]“]

OBS: trocar [] por MENOR MAIOR…


Muito mau mesmo. Esta solução é péssima!

em particular porque o seguinte é falso:
… se você coloca uma query string (algo como “?alguma-coisa”) após o nome do arquivo, este é tratado pelo browser como um novo arquivo, e a versão em cache é descartada em favor de uma nova versão, que será baixada do servidor.

Na verdade, o ficheiro é tratado como uma nova entrada na cache, mas a anterior ou anteriores não são eliminadas, excepto quando a cache atingir o seu limite.

Embora isto garante que se carrega o ficheiro novo, também está a fazer “trashing” da cache, em particular quando em desenvolvimento. Pois estaremos a encher a cache com novas versões (alteradas) do mesmo ficheiro, em vez de substituir a actual versão, ou simplesmente não fazer cache da mesma.

Qualquer WebServer decente (incluindo Apache, IIS, etc..), permite definir, qual o tempo de cache a devolver segundo o protocolo HTTP.
Normalmente permitem configurar isto pelas extensão do ficheiro (*.css) ou ficheiro a ficheiro, ou ambas.

Assim, no servidor de Desenvolvimento, basta definir que os ficheiros CSS não devem ter cache, usando as funcionalidades providenciadas pelo servidor.

No servidor de Produção, deverão configurar a cache para algo razoável, tal como uma semana, um dia ou uma hora. dependendo da frequencia das eventuais actualizações.

Para além disto, o browser gere a cache de forma correcta.

Com esta solução, não se faz trashing da cache do browser e utilizam-se as “features” correctas dos standards.


#21 | Antonio Augusto André Silveira

Olá,

Não quero evitar catching, aliás, quero realmente deixar o catching normal.

Diria o mesmo que o Daniel Luz.

Agora uma coisa, se eu deixar por exemplo meu arquivo css assim: meusestilos.php, como não existe o sinal de interrogação (?), dizendo que existem querystrings, então não é carregado novamente toda vez que acessado, isto é, ele é carregado do cache, certo?


[...] Remembering to post i read in the last few days (Avoiding caching when (and only when) the CSS file is updated (Portuguese Post) and Modular CSS – Small explanation (Portuguese Post)), came to me an interesting idea that could solve my problem. [...]


Oi Bruno, também fiz o mesmo para o meu caso. Funciona beleza, até porque eu uso PHP para personalizar o CSS… mas você sabe de algum senão nessa história toda. Tem alguma desvantagem/perda por estar usando QueryString? Sei lá, algum problema de não reconhecimento com algum agente?
Valeu.


Parabéns, era realmente o que estava procurando e, especificadamente, utilizei a ultima maneira indicada, mas um pouquinho modificada:

<?php bloginfo(‘stylesheet_url’); ?>?data-atualizacao=<?php echo filemtime(dirname(__FILE__).’/style.css’); ?>

No caso, eu modifico pra caramba o tema e a isso “caiu como uma luva”… :wink:


Bom dia a todos.
Graças a DEUS há pessoas que compartilham seus conhecimentos !!!
Importante informação sobre dicas de melhores formas para fazer certo sites e publicações.
Costumo colocar na meta tag , Indicação de não colocar no cache do browser, ou seja sempre vai buscar nova página.
Essa meta tag tambem está se referindo ao CSS?


[...] de cache css e até que o truque é bem simples. Leia o artigo e confira a diga do colega no site: http://www.brunotorres.net Ofertas RelacionadasSmarthphone Mp20 F026 Trackball Msn Wi Fi Quadriband JavaMais info»R$ [...]


«

»

Deixe seu comentário