Bonjours, je commence une série d’articles pour vous montrer la solution mise en place pour compresser les en-têtes de votre site.

Attention, pour le moment la solution n’est pas encore 100% fonctionnelle, à l’heure où j’écris ces lignes, sur le site je fonctionne encore avec le Zend_Cache utilisant les fichiers. En local, je travail avec Zend_Cache utilisant le cache APC. Certains problèmes me sont apparus avec les fichiers et ils ont disparus avec APC.

Donc tout d’abord je vais vous présenter le filtre que j’utilise pour compresser le contenu de mes fichiers CSS, ensuite je vous présente la méthode utilisée pour récupérer dans mon layout tous les appels à mes styles et pour finir comment je fais croire qu’il y a qu’un seul fichier CSS.

Attention: dans les exemples que je vais vous montrer, je vais faire appel à la classe App_Cache. Cette classe est donnée dans le livre Zend Framework – Bien développer en php.

Tout d’abord, pour compresser le contenu des fichiers CSS j’utilise le filtre présent ci-dessous. Il permet de supprimer toutes les tabulations, espaces en trop, commentaires présents dans le fichier.

/**
* Filtre servant à compresser des données CSS lors de la mise en cache par exemple.
*
* Supprime les espaces en trop, les commentaires et met tout sur une seule ligne.
*
* @author Throrin
*
*/
class App_Filter_CssCompressor implements Zend_Filter_Interface
{
public function filter($value)
{
$value = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $value);
$value = str_replace(array("\r\n", "\r", "\n", "\t", ' '), '', $value);
$value = str_replace('{ ', '{', $value);
$value = str_replace(' }', '}', $value);
$value = str_replace('; ', ';', $value);
$value = str_replace(', ', ',', $value);
$value = str_replace(' {', '{', $value);
$value = str_replace('} ', '}', $value);
$value = str_replace(': ', ':', $value);
$value = str_replace(' ,', ',', $value);
$value = str_replace(' ;', ';', $value);

return $value;
}
}

Ensuite, nous devons commencer par rajouter certaines lignes dans la partie contenant tous nos appels au CSS. Pour ce faire j’utilise la fonction ob_start() de PHP permettant de stocker ce qui suit dans un buffer et je le récupère avec la fonction ob_get_contents(). Pour finir à la suite de sa je ferais appel aux actions qui serviront à stocker le tout dans le cache grâce à la fonction $this->action().

<

headScript()."\n"; ?>


jQuery()->addStylesheet($this->baseUrl().'/styles/jquery-ui-1.7.2.custom.css')
->setUiLocalPath($this->baseUrl().'/scripts/jquery-ui-1.7.2.custom.min.js')
->setLocalPath($this->baseUrl().'/scripts/jquery-1.3.2.min.js')."\n"; ?>

action('compresscss', 'header', 'compress', array('contenu' => $output));
ob_end_clean();
?>

Voilà pour ici, maintenant on s’attaque à notre contrôleur qui va parcourir le contenu du buffer pour récupérer le lien vers chaque CSS. Ensuite il va lire le contenu des CSS, le compresser grâce à notre filtre et envoyer son contenu en cache. Pour éviter de répéter cette action assez lourde à chaque appel de l’action, on testera si le cache a bien été créé.

class Compress_HeaderController extends Zend_Controller_Action
{
public function compresscssAction()
{
$css = App_Cache::get('csssite');

if(!$css) {
$cssoffset = $this->_request->getParam('contenu');

//on récupère tous les fichiers CSS
preg_match_all('/link rel="stylesheet" href="(.*?)"/', $cssoffset, $matches);
$i = 0;
$n = count($matches[1]);
$contenucss = '';
//on parcour le tableau des fichiers CSS
while($i < $n) { $lienscss = str_replace('//', '/', $_SERVER['DOCUMENT_ROOT']."/zendtuto18/public"); //lien absolu vers votre dossier public $liens = str_replace('/test18', '', $matches[1][$i]); $handle = fopen($lienscss.$liens,'r'); $contenucss .= fread($handle, filesize($lienscss.$liens)); $i++; } $filtrecss = new App_Filter_CssCompressor(); $contenucss = $filtrecss->filter($contenucss);

App_Cache::set($contenucss, 'csssite');
}
}
}

Voilà pour le contrôleur. Le problème c’est qu’il faut bien dire quel CSS on affiche. C’est pourquoi dans la vue de cette action vous allez mettre juste cette ligne:


Maintenant il y a une question qui vous brûle les levres et qui doit être: « Qu’est-ce que ce fichier style.css? ». Ce fichier est en fait un lien vers notre action d’affichage. Pour ce faire nous devons créer la règle de réécriture présente ci-dessous (htaccess et zend_route).

.htaccess :

RewriteRule ^(.*)styles/style.css$ /compress/header/css [L]

bootstrap.php dans l’action _initRoute() :

$router->addRoute(
'manageCSS',
new Zend_Controller_Router_Route('styles/style.css', array('module' => 'compress', 'controller'=>'header','action'=>'css'))
);

Voilà, cette règle a été nécessaire pour pas casser tous les liens relatifs présents dans les fichiers CSS. Ensuite il ne vous reste plus qu’à créer cette action dans le contrôleur header afin d’afficher le style:

public function cssAction()
{
$this->_helper->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
$css = App_Cache::get('css');

$this->getResponse()->setHeader("Content-type","text/css; charset: UTF-8");
$this->getResponse()->setHeader("Cache-Control","must-revalidate");
$offset = 60 * 60 ;
$ExpStr = gmdate("D, d M Y H:i:s",time() + $offset) . " GMT";
$this->getResponse()->setHeader("Expires: ", $ExpStr);
echo $css;
}

Après ceci tout devrai fonctionner comme sur des roulettes. Pour la partie JS tout est à peu près de ce genre. Seules quelques étapes supplémentaires sont nécessaires pour tout récupérer. J’espère que cet article vous aura permi de trouver une méthode pour compresser vos styles. Par contre évitez de l’utiliser pour un site necessitant un fichier CSS différent par pages. Effectivement en cache vous aurez que le contenu des css inclus dans la première page.