Eu vs cache. Ganhei a batalha

Quem aqui nunca atualizou uma página web, alterou um CSS, JS ou imagem, enviou e-mail para o cliente e ele disse que na máquina dele não aparece?

Eu consegui ganhar esta batalha e de uma forma muito boa e ainda melhorar o pagespeed dos meus sites. Como? Muito simples.

Para este exemplo não se esqueça que a pasta site_cache precisa de permissão de escrita.

Primeiro eu criei uma classe CompilaCss e nesta classe fiz a seguinte estrutura:

<?php
class CompilaCss 
{
    private $css = array();
 
    private $filemtime = 0;
    private $file      = '';
 
    public function addCss( $cssName )
    {
        $this->css[] = $cssName;
 
        // Soma todos as datas de alterações do arquivo
        // Aqui esta a mágica. Mudando algum CSS a soma dos filemtime serão
        // diferentes
        $this->filemtime += filemtime( $cssName );
    }
     
    public function linkCss( $base )
    {
        $this->file = 'site_cache/css_' . md5( $this->filemtime ) . '.css';
 
        if( !file_exists( $this->file ))
        {
            // Se o arquivo do CSS ainda não existir, cria outro. 
            // Basicamente se mudar algum filemtime de qualquer arquivo
            // um novo arquivo é criado
            $this->createCssFile();
        }
 
        echo '<link href="' . $base . $this->file . '" rel="stylesheet" type="text/css" />';
    }
     
    private function createCssFile()
    {
        $salvaCSS = '';
 
        foreach ( $this->css as $css )
        {
            // Pega o conteúdo dos arquivos CSS
            // adiciona todos os conteúdos a variável $salvaCSS
            $salvaCSS .= file_get_contents( $css );
        }
 
        // Retira todos os comentários
        $salvaCSS = preg_replace('!/\*.*?\*/!s', ' ', $salvaCSS);
        // Retira todos os espaços em branco e quebras de linhas
        $salvaCSS = preg_replace('/\s+/', ' ', $salvaCSS);

        // espaços extras
        $salvaCSS = str_replace(' :', ':', $salvaCSS);
        $salvaCSS = str_replace('; ', ';', $salvaCSS);
        $salvaCSS = str_replace(': ', ':', $salvaCSS);
        $salvaCSS = str_replace(' {', '{', $salvaCSS);
        $salvaCSS = str_replace('{ ', '{', $salvaCSS);
        $salvaCSS = str_replace(' }', '}', $salvaCSS);
        $salvaCSS = str_replace('} ', '}', $salvaCSS);
        $salvaCSS = str_replace(';} ', '}', $salvaCSS);
 
        // Salva
        file_put_contents( $this->file, $salvaCSS );
    }
}

Veja que em addCss($cssName) eu apenas adiciono todos os CSS em um array e acrescento o valor do filemtime do arquivo á $this->filemtime.

Já foi possível perceber que se eu alterar qualquer arquivo CSS o filemtime será diferente e por padrão teremos uma soma diferente.

Para adicionarmos CSS fazemos assim:

<?php
$css = new CompilaCss();
$css->addCss('css/erro.css');
$css->addCss('css/style.css');
$css->addCss('modulos/lightbox/css/jquery.lightbox-0.5.css');
$css->addCss( 'css/style-print.css' );
$css->linkCss( URL::getBase() );
Parte do site www.cidadedesaobonifacio.com.br. Qualquer um dos CSS acima podem ser acessados normalmente prefixando com o domínio.
Ex: www.cidadedesaobonifacio.com.br/css/style-print.css

Sempre que for chamado $css->linkCss( URL::getBase() ); a classe verificará se o arquivo já compilado existe e se não existe criará um arquivo novo. Se já existe apenas retorna o link. Caso não exista primeiro compila o arquivo e depois retorna o link.

O método createCssFile() além de unir todos os CSS em um único arquivo, também remove os caracteres em branco sobrando, retira os comentários e as quebras de linha.

Veja este sistema funcionando em: php.eduardokraus.com/code/10044/ e o fonte esta em php.eduardokraus.com/code/10044/10044.zip.

Fique por dentro de nossas novidades, ideias e atualizações