2012-06-12 6 views
11

Ho fatto un po 'di guardarmi intorno, ma sono ancora un po' confuso.Come minimizzare JS in PHP facilmente ... O qualcos'altro

Ho provato il JSMin di Crockford, ma Win XP non può decomprimere il file eseguibile per qualche motivo.

Quello che voglio veramente è un minificatore JS semplice e facile da usare che utilizza PHP per minimizzare il codice JS e restituire il risultato.

Il motivo è perché: ho 2 file (per esempio) che sto lavorando tra: scripts.js e scripts_template.js

scripts_template è codice normale che scrivo fuori - allora ho per ridimensionarlo e incollare lo script minificato in scripts.js - quello che effettivamente utilizzo sul mio sito web.

Voglio sradicare l'uomo medio, semplicemente facendo qualcosa di simile sulla mia pagina:

<script type="text/javascript" src="scripts.php"></script> 

E poi per i contenuti dei scripts.php:

<?php include("include.inc"); header("Content-type:text/javascript"); echo(minify_js(file_get_contents("scripts_template.js"))); 

In questo modo, ogni volta che aggiorna il mio JS, non devo andare costantemente su un sito web per ridimensionarlo e re-incollarlo in scripts.js - tutto viene aggiornato automaticamente.

Sì, ho provato anche PHP Minifier di Crockford e ho dato un'occhiata a PHP Speedy, ma non capisco le classi PHP ancora ... C'è qualcosa là fuori che una scimmia potrebbe capire, forse qualcosa con RegExp?

Che ne dici di renderlo ancora più semplice?

Voglio solo rimuovere gli spazi delle schede - Voglio comunque che il mio codice sia leggibile.

Non è che la sceneggiatura rallenti il ​​mio sito in modo epico, è tutto meglio di niente.

Rimozione scheda, chiunque? E se possibile, che ne dici di rimuovere completamente le linee BLANK?

+5

un regexp non sta minimizzando il codice JS in qualsiasi momento presto. –

+0

** Correlati: ** http://stackoverflow.com/a/33844247/1163000 –

risposta

21

Ho utilizzato un PHP implementation di JSMin entro il Douglas Crockford per un po 'di tempo. Può essere un po 'rischioso quando si concatenano i file, in quanto potrebbe esserci un punto e virgola mancante alla fine di una chiusura.

Sarebbe una saggia idea memorizzare nella cache l'output minified ed echo ciò che viene memorizzato nella cache a patto che sia più nuovo del file sorgente.

require 'jsmin.php'; 

if(filemtime('scripts_template.js') < filemtime('scripts_template.min.js')) { 
    read_file('scripts_template.min.js'); 
} else { 
    $output = JSMin::minify(file_get_contents('scripts_template.js')); 
    file_put_contents('scripts_template.min.js', $output); 
    echo $output; 
} 

Si potrebbe anche provare JShrink. Non l'ho mai usato prima, dal momento che non ho avuto difficoltà con JSMin prima, ma questo codice qui sotto dovrebbe fare il trucco. Non me ne ero reso conto, ma JShrink richiede PHP 5.3 e namespace.

require 'JShrink/Minifier.php'; 

if(filemtime('scripts_template.js') < filemtime('scripts_template.min.js')) { 
    read_file('scripts_template.min.js'); 
} else { 
    $output = \JShrink\Minifier::minify(file_get_contents('scripts_template.js')); 
    file_put_contents('scripts_template.min.js', $output); 
    echo $output; 
} 
+0

Ho provato a utilizzare questo, ma non minimizzare l'intero codice. In effetti, codifica il codice CUTS a metà dello script, quindi sono nel bel mezzo di un ciclo for(), che comunque causerebbe la corruzione dello script. – RickyAYoder

+0

@RickyAYoder Sono state visualizzate notifiche o errori? Potrebbe essere un errore di sintassi nel tuo Javascript. –

+0

No. Quando eseguo lo script fatto a mano e non minorato, non ci sono errori da segnalare. – RickyAYoder

2

In base alle restrizioni del server (ad esempio, non è in esecuzione in safe mode), forse si può anche guardare al di là di PHP per una minifier ed eseguirlo con shell_exec().Ad esempio, se è possibile eseguire Java sul server, inserire una copia di YUI Compressor sul server e utilizzarla direttamente.

Poi scripts.php sarebbe qualcosa di simile:

<?php 

    $cmd = "java -cp [path-to-yui-dir] -jar [path-to-yuicompressor.jar] [path-to-scripts_template.js]"; 

    echo(shell_exec($cmd)); 

?> 

altro suggerimento: costruire il passo minification nel flusso di lavoro di sviluppo, prima di distribuire al server. Ad esempio, ho impostato i miei progetti PHP Eclipse per comprimere i file JS e CSS in una cartella "build". Funziona come un fascino.

+2

L'avvio di un'app JAVA per una piccola utility sembra un enorme aumento per me. Sarebbe impossibile adattare questa soluzione in un flusso di richiesta-risposta come l'OP voleva. – karatedog

+1

Quello che dici non è esclusivamente vero di un'app Java. Ri-minifying su ogni richiesta sarebbe una spesa inutile con qualsiasi utilità. Nota [precedente consiglio di Robert-K] (http://stackoverflow.com/a/11000599/1301247) per memorizzare nella cache il risultato, o il mio "altro suggerimento", per spostarlo in una fase di compilazione automatizzata. Ora, tre anni dopo, ci sono comunque opzioni migliori per minimizzare di YUI. –

0

Utilizzando "PHPWee": https://github.com/searchturbine/phpwee-php-minifier (che utilizza anche JSmin), ho spinto soluzione @ Robert K un po 'oltre.

Questa soluzione consente di minimizzare sia i file CSS che JS. Se il file non minificato non può essere trovato, restituirà una stringa vuota. Se il file minificato è più vecchio del non miniato, proverà a crearlo. Creerà una sottocartella per il file minificato se non esiste. Se il metodo riesce a ridimensionare correttamente il file, lo restituisce in un tag <script> (javascript) o <link> (CSS). In caso contrario, il metodo restituirà la versione non minificata nel tag corretto.

Nota: testato con PHP 7.0.13

/** 
* Try to minify the JS/CSS file. If we are not able to minify, 
* returns the path of the full file (if it exists). 
* 
* @param $matches Array 
* 0 = Full partial path 
* 1 = Path without the file 
* 2 = File name and extension 
* 
* @param $fileType Boolean 
* FALSE: css file. 
* TRUE: js file 
* 
* @return String 
*/ 
private static function createMinifiedFile(array $matches, bool $fileType) 
{ 
    if (strpos($matches[1], 'shared_code') !== false) { 

     $path = realpath(dirname(__FILE__)) . str_replace(
      'shared_code', 
      '..', 
      $matches[1] 
     ); 

    } else { 

     $path = realpath(dirname(__FILE__)) . 
      "/../../" . $matches[1]; 
    } 

    if (is_file($path . $matches[2])) { 

     $filePath = $link = $matches[0]; 

     $min = 'min/' . str_replace(
      '.', 
      '.min.', 
      $matches[2] 
     ); 

     if (!is_file($path . $min) or 
      filemtime($path . $matches[2]) > 
      filemtime($path . $min) 
     ) { 

      if (!is_dir($path . 'min')) { 

       mkdir($path . 'min'); 
      } 

      if ($fileType) { // JS 

       $minified = preg_replace(
         array(
          '/(\))\R({)/', 
          '/(})\R/' 
         ), 
         array(
          '$1$2', 
          '$1' 
         ), 
         Minify::js(
         (string) file_get_contents(
          $path . $matches[2] 
         ) 
        ) 
       ); 

      } else { // CSS 

       $minified = preg_replace(
        '@/\*(?:[\r\s\S](?!\*/))+\R?\*/@', //deal with multiline comments 
        '', 
        Minify::css(
         (string) file_get_contents(
          $path . $matches[2] 
         ) 
        ) 
       ); 
      } 

      if (!empty($minified) and file_put_contents(
        $path . $min, 
        $minified 
       ) 
      ) { 

       $filePath = $matches[1] . $min; 
      } 

     } else { // up-to-date 

      $filePath = $matches[1] . $min; 
     } 

    } else { // full file doesn't exists 

     $filePath = ""; 
    } 

    return $filePath; 
} 

/** 
* Return the minified version of a CSS file (must end with the .css extension). 
* If the minified version of the file is older than the full CSS file, 
* the CSS file will be shrunk. 
* 
* Note: An empty string will be return if the CSS file doesn't exist. 
* 
* Note 2: If the file exists, but the minified file cannot be created, 
*  we will return the path of the full file. 
* 
* @link https://github.com/searchturbine/phpwee-php-minifier Source 
* 
* @param $path String name or full path to reach the CSS file. 
* If only the file name is specified, we assume that you refer to the shared path. 
* 
* @return String 
*/ 
public static function getCSSMin(String $path) 
{ 
    $link = ""; 
    $matches = array(); 

    if (preg_match(
      '@^(/[\w-]+/view/css/)?([\w-]+\.css)[email protected]', 
      $path, 
      $matches 
     ) 
    ) { 

     if (empty($matches[1])) { // use the default path 

      $matches[1] = self::getCssPath(); 

      $matches[0] = $matches[1] . $matches[2]; 
     } 

     $link = self::createMinifiedFile($matches, false); 

    } else { 

     $link = ""; 
    } 

    return (empty($link) ? 
     '' : 
     '<link rel="stylesheet" href="' . $link . '">' 
    ); 
} 

/** 
* Return the path to fetch CSS sheets. 
* 
* @return String 
*/ 
public static function getCssPath() 
{ 
    return '/shared_code/css/' . self::getCurrentCSS() . "/"; 
} 

/** 
* Return the minified version of a JS file (must end with the .css extension). 
* If the minified version of the file is older than the full JS file, 
* the JS file will be shrunk. 
* 
* Note: An empty string will be return if the JS file doesn't exist. 
* 
* Note 2: If the file exists, but the minified file cannot be created, 
*  we will return the path of the full file. 
* 
* @link https://github.com/searchturbine/phpwee-php-minifier Source 
* 
* @param $path String name or full path to reach the js file. 
* 
* @return String 
*/ 
public static function getJSMin(String $path) 
{ 
    $matches = array(); 

    if (preg_match(
      '@^(/[\w-]+(?:/view)?/js/)([\w-]+\.js)[email protected]', 
      $path, 
      $matches 
     ) 
    ) { 
     $script = self::createMinifiedFile($matches, true); 

    } else { 

     $script = ""; 
    } 

    return (empty($script) ? 
     '' : 
     '<script src="' . $script . '"></script>' 
    ); 
} 

In un (Smarty) modello, si potrebbe utilizzare gli stessi metodi come questo:

{$PageController->getCSSMin("main_frame.css")} 
//Output: <link rel="stylesheet" href="/shared_code/css/default/min/main_frame.min.css"> 

{$PageController->getCSSMin("/gem-mechanic/view/css/gem_mechanic.css")} 
//Output: <link rel="stylesheet" href="/gem-mechanic/view/css/min/gem_mechanic.min.css"> 

{$PageController->getJSMin("/shared_code/js/control_utilities.js")} 
//Output: <script src="/shared_code/js/min/control_utilities.min.js"></script> 

{$PageController->getJSMin("/PC_administration_interface/view/js/error_log.js")} 
//Output: <script src="/PC_administration_interface/view/js/min/error_log.min.js"></script> 

test di unità:

/** 
* Test that we can minify CSS files successfully. 
*/ 
public function testGetCSSMin() 
{ 
    //invalid style 
    $this->assertEmpty(
     PageController::getCSSMin('doh!!!') 
    ); 


    //shared style 
    $path = realpath(dirname(__FILE__)) . '/../css/default/min/main_frame.min.css'; 

    if (is_file($path)) { 

     unlink ($path); 
    } 

    $link = PageController::getCSSMin("main_frame.css"); 

    $this->assertNotEmpty($link); 

    $this->assertEquals(
     '<link rel="stylesheet" href="/shared_code/css/default/min/main_frame.min.css">', 
     $link 
    ); 

    $this->validateMinifiedFile($path); 


    //project style 
    $path = realpath(dirname(__FILE__)) . '/../../gem-mechanic/view/css/min/gem_mechanic.min.css'; 

    if (is_file($path)) { 

     unlink ($path); 
    } 

    $link = PageController::getCSSMin("/gem-mechanic/view/css/gem_mechanic.css"); 

    $this->assertNotEmpty($link); 

    $this->assertEquals(
     '<link rel="stylesheet" href="/gem-mechanic/view/css/min/gem_mechanic.min.css">', 
     $link 
    ); 

    $this->validateMinifiedFile($path); 
} 

/** 
* Test that we can minify JS files successfully. 
*/ 
public function testGetJSMin() 
{ 
    //invalid script 
    $this->assertEmpty(
     PageController::getJSMin('doh!!!') 
    ); 


    //shared script 
    $path = realpath(dirname(__FILE__)) . '/../js/min/control_utilities.min.js'; 

    if (is_file($path)) { 

     unlink ($path); 
    } 

    $script = PageController::getJSMin("/shared_code/js/control_utilities.js"); 

    $this->assertNotEmpty($script); 

    $this->assertEquals(
     '<script src="/shared_code/js/min/control_utilities.min.js"></script>', 
     $script 
    ); 

    $this->validateMinifiedFile($path); 


    //project script 
    $path = realpath(dirname(__FILE__)) . '/../../PC_administration_interface/view/js/min/error_log.min.js'; 

    if (is_file($path)) { 

     unlink ($path); 
    } 

    $script = PageController::getJSMin("/PC_administration_interface/view/js/error_log.js"); 

    $this->assertNotEmpty($script); 

    $this->assertEquals(
     '<script src="/PC_administration_interface/view/js/min/error_log.min.js"></script>', 
     $script 
    ); 

    $this->validateMinifiedFile($path); 
} 

/** 
* Make sure that the minified file exists and that its content is valid. 
* 
* @param $path String the path to reach the file 
*/ 
private function validateMinifiedFile(string $path) 
{ 
    $this->assertFileExists($path); 

    $content = (string) file_get_contents($path); 

    $this->assertNotEmpty($content); 

    $this->assertNotContains('/*', $content); 

    $this->assertEquals(
     0, 
     preg_match(
      '/\R/', 
      $content 
     ) 
    ); 
} 

Ulteriori note:

  1. In phpwee.php ho dovuto sostituire <? da <?php.
  2. Ho avuto problemi con lo spazio dei nomi (la funzione class_exists() non è stata in grado di trovare le classi anche se si trovavano nello stesso file). Ho risolto questo problema rimuovendo lo spazio dei nomi in ogni file.