Changeset 43372 in spip-zone


Ignore:
Timestamp:
Jan 7, 2011, 1:20:54 PM (10 years ago)
Author:
cedric@…
Message:

refactoring du compresseur :
concatener toutes les css en une seule, sans en modifier l'ordre, mais en prefixant leur contenu du @media correspondant a son media
De ce fait, reecriture des fonctions compacte_head_css et compacte_head_js en une seule fonction compacte_head_files commune
L'insertion dans le head du fichier compresse est deleguee aux fonctions
compacte_ecrire_balise_css et compacte_ecrire_balise_css qui peuvent decider de la forme et du point d'insertion les plus pertinents (balise simple, dom insertion par js etc ...)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • _core_/plugins/compresseur/inc/compresseur.php

    r42397 r43372  
    11<?php
    22
    3 function compacte_ecrire_balise_script_dist($src){
    4         return "<script type='text/javascript' src='$src'></script>";
    5 }
    6 function compacte_ecrire_balise_link_dist($src,$media=""){
    7         return "<link rel='stylesheet'".($media?" media='$media'":"")." href='$src' type='text/css' />";
     3/***************************************************************************\
     4 *  SPIP, Systeme de publication pour l'internet                           *
     5 *                                                                         *
     6 *  Copyright (c) 2001-2011                                                *
     7 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
     8 *                                                                         *
     9 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
     10 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
     11\***************************************************************************/
     12
     13if (!defined("_ECRIRE_INC_VERSION")) return;
     14
     15/**
     16 * Ecrire la balise javascript pour inserer le fichier compresse
     17 * C'est cette fonction qui decide ou il est le plus pertinent
     18 * d'inserer le fichier, et dans quelle forme d'ecriture
     19 *
     20 * @param string $flux
     21 *   contenu du head nettoye des fichiers qui ont ete compresse
     22 * @param int $pos
     23 *   position initiale du premier fichier inclu dans le fichier compresse
     24 * @param string $src
     25 *   nom du fichier compresse
     26 * @param string $comments
     27 *   commentaires a inserer devant
     28 * @return string
     29 */
     30function compacte_ecrire_balise_js_dist(&$flux, $pos, $src, $comments = ""){
     31        $comments .= "<script type='text/javascript' src='$src'></script>";
     32  $flux = substr_replace($flux,$comments,$pos,0);
     33  return $flux;
     34}
     35
     36/**
     37 * Ecrire la balise css pour inserer le fichier compresse
     38 * C'est cette fonction qui decide ou il est le plus pertinent
     39 * d'inserer le fichier, et dans quelle forme d'ecriture
     40 *
     41 * @param string $flux
     42 *   contenu du head nettoye des fichiers qui ont ete compresse
     43 * @param int $pos
     44 *   position initiale du premier fichier inclu dans le fichier compresse
     45 * @param string $src
     46 *   nom du fichier compresse
     47 * @param string $comments
     48 *   commentaires a inserer devant
     49 * @return string
     50 */
     51function compacte_ecrire_balise_css_dist(&$flux, $pos, $src, $comments = "", $media=""){
     52        $comments .= "<link rel='stylesheet'".($media?" media='$media'":"")." href='$src' type='text/css' />";
     53  $flux = substr_replace($flux,$comments,$pos,0);
     54        return $flux;
    855}
    956
     
    131178
    132179/**
    133  * Compacte du javascript grace a Dean Edward's JavaScriptPacker
    134  *
    135  * Bench du 15/11/2010 sur jQuery.js :
    136  * JSMIN (https://github.com/rgrove/jsmin-php/)
    137  *      61% de la taille initiale / 2 895 ms
    138  * JavaScriptPacker
    139  *  62% de la taille initiale / 752 ms
    140  *
    141  * Closure Compiler
    142  *  44% de la taille initiale / 3 785 ms
    143  *
    144  * JavaScriptPacker + Closure Compiler
    145  *  43% de la taille initiale / 3 100 ms au total
    146  *
    147  * Il est donc plus rapide&efficace
    148  * - de packer d'abord en local avec JavaScriptPacker
    149  * - d'envoyer ensuite au closure compiler
    150  * Cela permet en outre d'avoir un niveau de compression decent si closure
    151  * compiler echoue
    152  *
    153  * Dans cette fonction on ne fait que le compactage local,
    154  * l'appel a closure compiler est fait une unique fois pour tous les js concatene
    155  * afin d'eviter les requetes externes
     180 * Extraire les balises CSS a compacter et retourner un tableau
     181 * balise => src
    156182 *
    157  * @param string $flux
    158  * @return string
     183 * @param  $flux
     184 * @param  $url_base
     185 * @return array
    159186 */
    160187function compacte_js($flux) {
     
    176203 * Compacter du javascript plus intensivement
    177204 * grace au google closure compiler
    178  * 
     205 *
    179206 * @param string $content
    180207 * @param bool $file
    181  * @return string 
     208 * @return string
    182209 */
    183210function compacte_js_more($content,$file=false) {
     
    235262
    236263
    237 // Appelee par compacte_head() si le webmestre le desire, cette fonction
    238 // compacte les scripts js dans un fichier statique pose dans local/
    239 // en entree : un <head> html.
    240 // http://doc.spip.org/@compacte_head_js
    241 function compacte_head_js($flux) {
     264/**
     265 * Extraire les balises CSS a compacter et retourner un tableau
     266 * balise => src
     267 *
     268 * @param  $flux
     269 * @param  $url_base
     270 * @return array
     271 */
     272function extraire_balises_css_dist($flux, $url_base){
     273        $balises = extraire_balises($flux,'link');
     274        $files = array();
     275        foreach ($balises as $s){
     276                if (extraire_attribut($s, 'rel') === 'stylesheet'
     277                        AND (!($type = extraire_attribut($s, 'type'))
     278                                OR $type == 'text/css')
     279                        AND is_null(extraire_attribut($s, 'name')) # css nommee : pas touche
     280                        AND is_null(extraire_attribut($s, 'id'))   # idem
     281                        AND !strlen(strip_tags($s))
     282                        AND $src = preg_replace(",^$url_base,",_DIR_RACINE,extraire_attribut($s, 'href')))
     283                        $files[$s] = $src;
     284        }
     285        return $files;
     286}
     287
     288/**
     289 * Extraire les balises JS a compacter et retoruner un tableau
     290 * balise => src
     291 * @param  $flux
     292 * @param  $url_base
     293 * @return array
     294 */
     295function extraire_balises_js_dist($flux, $url_base){
     296        $balises = extraire_balises($flux,'script');
     297        $files = array();
     298        foreach ($balises as $s){
     299                if (extraire_attribut($s, 'type') === 'text/javascript'
     300                        AND $src = extraire_attribut($s, 'src')
     301                        AND !strlen(strip_tags($s)))
     302                        $files[$s] = $src;
     303        }
     304        return $files;
     305}
     306
     307/**
     308 * Compacter (concatener+minifier) les fichiers format css ou js
     309 * du head. Reperer fichiers statiques vs url squelettes
     310 * Compacte le tout dans un fichier statique pose dans local/
     311 *
     312 * @param string $flux
     313 *  contenu du <head> de la page html
     314 * @param string $format
     315 *  css ou js
     316 * @return string
     317 */
     318function compacte_head_files($flux,$format) {
    242319        $url_base = url_de_base();
    243320        $url_page = substr(generer_url_public('A'), 0, -1);
    244321        $dir = preg_quote($url_page,',').'|'.preg_quote(preg_replace(",^$url_base,",_DIR_RACINE,$url_page),',');
    245322
    246         $scripts = array();
     323        if (!$extraire_balises = charger_fonction("extraire_balises_$format",'',true))
     324                return $flux;
     325
     326        $files = array();
    247327        $flux_nocomment = preg_replace(",<!--.*-->,Uims","",$flux);
    248         foreach (extraire_balises($flux_nocomment,'script') as $s) {
    249                 if (extraire_attribut($s, 'type') === 'text/javascript'
    250                 AND $src = extraire_attribut($s, 'src')
    251                 AND !strlen(strip_tags($s))
    252                 AND (
     328        foreach ($extraire_balises($flux_nocomment, $url_base) as $s=>$src) {
     329                if (
    253330                        preg_match(',^('.$dir.')(.*)$,', $src, $r)
    254331                        OR (
     
    256333                                $src = preg_replace(',^'.preg_quote(url_de_base(),',').',', '', $src)
    257334                                // enlever un timestamp eventuel derriere un nom de fichier statique
    258                                 AND $src2 = preg_replace(",[.]js[?].+$,",'.js',$src)
     335                                AND $src2 = preg_replace(",[.]{$format}[?].+$,",".$format",$src)
    259336                                // verifier qu'il n'y a pas de ../ ni / au debut (securite)
    260337                                AND !preg_match(',(^/|\.\.),', substr($src,strlen(_DIR_RACINE)))
     
    262339                                AND @is_readable($src2)
    263340                        )
    264                 )) {
     341                ) {
    265342                        if ($r)
    266                                 $scripts[$s] = explode('&',
    267                                         str_replace('&amp;', '&', $r[2]), 2);
     343                                $files[$s] = explode('&', str_replace('&amp;', '&', $r[2]), 2);
    268344                        else
    269                                 $scripts[$s] = $src;
     345                                $files[$s] = $src;
    270346                }
    271347        }
    272348
    273         if (list($src,$comms) = filtre_cache_static($scripts,'js')){
    274                 $compacte_ecrire_balise_script = charger_fonction('compacte_ecrire_balise_script','');
    275                 $scripts = array_keys($scripts);
    276                 $flux = str_replace(reset($scripts),
    277                         $comms .$compacte_ecrire_balise_script($src)."\n",
    278                         $flux);
    279                 $flux = str_replace($scripts,"",$flux);
     349        if (list($src,$comms) = filtre_cache_static($files,$format)){
     350                $compacte_ecrire_balise = charger_fonction("compacte_ecrire_balise_$format",'');
     351                $files = array_keys($files);
     352                // retrouver la position du premier fichier compacte
     353                $pos = strpos($flux,reset($files));
     354                // supprimer tous les fichiers compactes du flux
     355                $flux = str_replace($files,"",$flux);
     356                // inserer la balise (deleguer a la fonction, en lui donnant le necessaire)
     357                $flux = $compacte_ecrire_balise($flux, $pos, $src, $comms);
    280358        }
    281359
     
    283361}
    284362
    285 // Appelee par compacte_head() si le webmestre le desire, cette fonction
    286 // compacte les feuilles de style css dans un fichier statique pose dans local/
    287 // en entree : un <head> html.
    288 // http://doc.spip.org/@compacte_head_css
    289 function compacte_head_css($flux) {
    290         $url_base = url_de_base();
    291         $url_page = substr(generer_url_public('A'), 0, -1);
    292         $dir = preg_quote($url_page,',').'|'.preg_quote(preg_replace(",^$url_base,",_DIR_RACINE,$url_page),',');
    293 
    294         $css = array();
    295         $flux_nocomment = preg_replace(",<!--.*-->,Uims","",$flux);
    296         foreach (extraire_balises($flux_nocomment, 'link') as $s) {
    297                 if (extraire_attribut($s, 'rel') === 'stylesheet'
    298                 AND (!($type = extraire_attribut($s, 'type'))
    299                         OR $type == 'text/css')
    300                 AND is_null(extraire_attribut($s, 'name')) # css nommee : pas touche
    301                 AND is_null(extraire_attribut($s, 'id'))   # idem
    302                 AND !strlen(strip_tags($s))
    303                 AND $src = preg_replace(",^$url_base,",_DIR_RACINE,extraire_attribut($s, 'href'))
    304                 AND (
    305                         // regarder si c'est du format spip.php?page=xxx
    306                         preg_match(',^('.$dir.')(.*)$,', $src, $r)
    307                         OR (
    308                                 // ou si c'est un fichier
    309                                 // enlever un timestamp eventuel derriere un nom de fichier statique
    310                                 $src2 = preg_replace(",[.]css[?].+$,",'.css',$src)
    311                                 // verifier qu'il n'y a pas de ../ ni / au debut (securite)
    312                                 AND !preg_match(',(^/|\.\.),', substr($src2,strlen(_DIR_RACINE)))
    313                                 // et si il est lisible
    314                                 AND @is_readable($src2)
    315                         )
    316                 )) {
    317                         $media = strval(extraire_attribut($s, 'media'));
    318                         if ($r)
    319                                 $css[$media][$s] = explode('&',
    320                                         str_replace('&amp;', '&', $r[2]), 2);
    321                         else
    322                                 $css[$media][$s] = $src;
    323                 }
    324         }
    325 
    326         // et mettre le tout dans un cache statique
    327         foreach($css as $m=>$s){
    328                 // si plus d'une css pour ce media ou si c'est une css dynamique
    329                 if (count($s)>1 OR is_array(reset($s))){
    330                         if (list($src,$comms) = filtre_cache_static($s,'css')){
    331                                 $compacte_ecrire_balise_link = charger_fonction('compacte_ecrire_balise_link','');
    332                                 $s = array_keys($s);
    333                                 $flux = str_replace(reset($s),
    334                                                                 $comms . $compacte_ecrire_balise_link($src,$m)."\n",
    335                                                                 $flux);
    336                                 $flux = str_replace($s,"",$flux);
    337                         }
    338                 }
    339         }
    340 
    341         return $flux;
    342 }
    343 
    344363
    345364// http://doc.spip.org/@filtre_cache_static
    346 function filtre_cache_static($scripts,$type='js'){
     365/**
     366 * Retrouve ou genere le fichier statique correspondant a une liste de fichiers
     367 * fournis en arguments
     368 * @param  $files
     369 * @param string $format
     370 * @return array
     371 */
     372function filtre_cache_static($files,$format='js'){
    347373        $nom = "";
    348         if (!is_array($scripts) && $scripts) $scripts = array($scripts);
    349         if (count($scripts)){
    350                 // on trie la liste de scripts pour calculer le nom
     374        if (!is_array($files) && $files) $files = array($files);
     375        if (count($files)){
     376                $minifier = 'compacte_'.$format;
     377         
     378                // on trie la liste de files pour calculer le nom
    351379                // necessaire pour retomber sur le meme fichier
    352380                // si on renome une url a la volee pour enlever le var_mode=recalcul
    353381                // mais attention, il faut garder l'ordre initial pour la minification elle meme !
    354                 $s2 = $scripts;
     382                $s2 = $files;
    355383                ksort($s2);
    356                 $dir = sous_repertoire(_DIR_VAR,'cache-'.$type);
    357                 $nom = $dir . md5(serialize($s2)) . ".$type";
     384                $dir = sous_repertoire(_DIR_VAR,'cache-'.$format);
     385                $nom = $dir . md5(serialize($s2)) . ".$format";
    358386                if (
    359387                        $GLOBALS['var_mode']=='recalcul'
     
    364392                        $total = 0;
    365393                        $s2 = false;
    366                         foreach($scripts as $key=>$script){
    367                                 if (!is_array($script)) {
     394                        foreach($files as $key=>$file){
     395                                if (!is_array($file)) {
    368396                                        // c'est un fichier
    369                                         $comm = $script;
     397                                        $comm = $file;
    370398                                        // enlever le timestamp si besoin
    371                                         $script = preg_replace(",[?].+$,",'',$script);
    372                                         if ($type=='css'){
     399                                        $file = preg_replace(",[?].+$,",'',$file);
     400                                        if ($format=='css'){
    373401                                                $fonctions = array('urls_absolues_css');
    374402                                                if (isset($GLOBALS['compresseur_filtres_css']) AND is_array($GLOBALS['compresseur_filtres_css']))
    375403                                                        $fonctions = $GLOBALS['compresseur_filtres_css'] + $fonctions;
    376                                                 $script = appliquer_fonctions_css_fichier($fonctions, $script);
     404                                                $file = appliquer_fonctions_css_fichier($fonctions, $file);
    377405                                        }
    378                                         lire_fichier($script, $contenu);
     406                                        lire_fichier($file, $contenu);
    379407                                }
    380408                                else {
    381409                                        // c'est un squelette
    382                                         $comm = _SPIP_PAGE . "=$script[0]"
    383                                                 . (strlen($script[1])?"($script[1])":'');
    384                                         parse_str($script[1],$contexte);
    385                                         $contenu = recuperer_fond($script[0],$contexte);
    386                                         if ($type=='css'){
     410                                        $comm = _SPIP_PAGE . "=$file[0]"
     411                                                . (strlen($file[1])?"($file[1])":'');
     412                                        parse_str($file[1],$contexte);
     413                                        $contenu = recuperer_fond($file[0],$contexte);
     414                                        if ($format=='css'){
    387415                                                $fonctions = array('urls_absolues_css');
    388416                                                if (isset($GLOBALS['compresseur_filtres_css']) AND is_array($GLOBALS['compresseur_filtres_css']))
     
    391419                                        }
    392420                                        // enlever le var_mode si present pour retrouver la css minifiee standard
    393                                         if (strpos($script[1],'var_mode')!==false) {
    394                                                 if (!$s2) $s2 = $scripts;
     421                                        if (strpos($file[1],'var_mode')!==false) {
     422                                                if (!$s2) $s2 = $files;
    395423                                                unset($s2[$key]);
    396424                                                $key = preg_replace(',(&(amp;)?)?var_mode=[^&\'"]*,','',$key);
    397                                                 $script[1] = preg_replace(',&?var_mode=[^&\'"]*,','',$script[1]);
    398                                                 $s2[$key] = $script;
     425                                                $file[1] = preg_replace(',&?var_mode=[^&\'"]*,','',$file[1]);
     426                                                $s2[$key] = $file;
    399427                                        }
    400428                                }
    401                                 $f = 'compacte_'.$type;
    402                                         $fichier .= "/* $comm */\n". $f($contenu) . "\n\n";
     429                                // minifier en passant le media en option si c'est une css
     430                                // (ignore pour les js)
     431                                $fichier .= "/* $comm */\n". $minifier($contenu, extraire_attribut($key,'media')) . "\n\n";
    403432                                $comms[] = $comm;
    404433                                $total += strlen($contenu);
     
    412441                        if ($s2) {
    413442                                ksort($s2);
    414                                 $nom = $dir . md5(serialize($s2)) . ".$type";
     443                                $nom = $dir . md5(serialize($s2)) . ".$format";
    415444                        }
    416445
     
    420449                        ecrire_fichier("$nom.gz",$fichier,true);
    421450                        // closure compiler ou autre super-compresseurs
    422                         $nom = compresse_encore($nom, $type);
     451                        // a appliquer sur le fichier final
     452                        $nom = compresse_encore($nom, $format);
    423453                }
    424454
     
    430460}
    431461
    432 // experimenter le Closure Compiler de Google
    433 function compresse_encore (&$nom, $type) {
     462/**
     463 * Minification additionnelle :
     464 * experimenter le Closure Compiler de Google
     465 * @param string $nom
     466 *   nom d'un fichier a minifier encore plus
     467 * @param string $format
     468 *   format css ou js
     469 * @return string
     470 */
     471function compresse_encore (&$nom, $format) {
    434472        # Closure Compiler n'accepte pas des POST plus gros que 200 000 octets
    435473        # au-dela il faut stocker dans un fichier, et envoyer l'url du fichier
     
    437475        if (
    438476        $GLOBALS['meta']['auto_compress_closure'] == 'oui'
    439         AND $type=='js'
     477        AND $format=='js'
    440478        ) {
    441479                $nom = compacte_js_more($nom,true);
Note: See TracChangeset for help on using the changeset viewer.