2012-06-12 23 views
11

我已經做了一些四處尋找,但我仍然有點困惑。如何在PHP中簡化JS ...或其他東西

我試過Crockford的JSMin,但Win XP由於某種原因無法解壓縮可執行文件。

我真正想要的是一個簡單易用的JS縮小器,它使用PHP縮小JS代碼並返回結果。

的原因是因爲: 我有2個文件(例如)說我之間的工作:scripts.js中和scripts_template.js

scripts_template的是,我寫出來正常代碼 - 然後,我有縮小它並將縮小的腳本粘貼到scripts.js中 - 我實際上在我的網站上使用的腳本。

我想簡單地做這樣的事情在我的網頁,以消除中間人:

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

然後爲scripts.php的內容:

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

這樣一來,每當我更新我的JS,我不必經常去一個網站來縮小它,並重新粘貼到scripts.js - 一切都會自動更新。

是的,我也試過Crockford的PHP Minifier,我看了一下PHP Speedy,但是我不明白PHP類是什麼......有什麼東西可以讓猴子理解,也許有東西與RegExp?

我們如何讓這更簡單?

我只想刪除標籤空格 - 我仍然希望我的代碼可讀。

這不像腳本讓我的網站滯後,它只是比任何事都好。

Tab刪除,任何人?如果可能的話,如何刪除完全空白的行?

+5

正則表達式不會很快縮小JS代碼。 –

+0

**相關:** http://stackoverflow.com/a/33844247/1163000 –

回答

21

我已經使用了JSMin的PHP implementationDouglas Crockford很長一段時間。連接文件時可能會有點冒險,因爲封閉結束時可能會丟失分號。

只要它比源文件更新,緩存縮小的輸出和回顯緩存的內容是明智的想法。

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; 
} 

您也可以嘗試JShrink。我以前從未使用過它,因爲我之前沒有遇到過JSMin的困難,但是下面的代碼應該可以做到。我沒有意識到這一點,但JShrink需要PHP 5.3和命名空間。

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

我試過使用這個,但它並沒有縮小整個代碼。實際上,它在腳本的一半處編碼,所以我正好處於for()循環的中間,這會導致腳本無論如何都會損壞。 – RickyAYoder

+0

@RickyAYoder是否有任何通知或錯誤輸出?這可能是你的Javascript語法錯誤。 –

+0

沒有。當我手動和未縮小腳本運行時,沒有錯誤需要報告。 – RickyAYoder

2

根據您的服務器(例如,不在safe mode運行)的限制,或許你也可以超越PHP的minifier和使用shell_exec()運行它。例如,如果您可以在服務器上運行Java,請將YUI Compressor的副本放在服務器上並直接使用它。

然後scripts.php會是這樣的:

<?php 

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

    echo(shell_exec($cmd)); 

?> 

其他建議:建立微小一步到您的開發流程,部署到服務器之前。例如,我設置了我的Eclipse PHP項目,將JS和CSS文件壓縮到「構建」文件夾中。奇蹟般有效。

+2

啓動一個JAVA應用程序的一個小實用程序似乎是一個巨大的膨脹對我來說。根據OP的要求,將這種解決方案放入請求響應流中是不可能的。 – karatedog

+1

你所說的並不完全適用於Java應用程序。對每個請求進行重新縮小對於任何實用程序都是不必要的開銷。請注意[Robert-K早先的建議](http://stackoverflow.com/a/11000599/1301247)來緩存結果或我的「其他建議」,將其移入自動構建步驟。現在,三年後,反正比YUI有更好的選擇。 –

0

使用 「PHPWee」:https://github.com/searchturbine/phpwee-php-minifier (也使用JSmin),I一點點進一步推@Robert K溶液。

該解決方案允許縮小CSS和JS文件。如果找不到縮小的文件,它將返回一個空字符串。如果縮小的文件比未縮小的文件大,它會嘗試創建它。如果它不存在,它將爲縮小文件創建一個子文件夾。如果該方法可以成功縮小文件,則它會以<script>(javascript)或<link>(CSS)標記的形式返回該文件。否則,該方法將在適當的標籤中返回未縮小的版本。

注意:用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>' 
    ); 
} 

測試在(Smarty的)模板,您可以使用這些方法是這樣的:

{$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 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 
     ) 
    ); 
} 

其他注意事項

  1. phpwee.php我不得不<?php更換<?
  2. 我遇到了命名空間問題(函數class_exists()無法找到類,即使它們在同一個文件中)。我通過刪除每個文件中的命名空間來解決此問題。