使用php在頁面輸出時,動態加載合併壓縮js

本文旨在解決php模板中模塊化視圖加載css樣式文件和js樣式的問題。

分模塊化的php模板中,控制器輸出的視圖旨在body標籤中,而不去關心頭部和尾部樣式。
這樣在模塊化視圖中加載其所需的樣式和js文件位置就成了一個問題。
這個問題可以通過在佈局的樣式模板中添加js和css替代變量解決,視圖中通過統一的方法去加載所需文件。

如果我們想優化頁面的加載速度,可以根據壓縮css和js文件提高頁面的訪問速度。同時合併文件又能再提高訪問速度。
於是乎,我採用了這用方法來優化腳本文件和訪問速度。
1.通過統一的方法將所需加載的文件路徑保存
2.在視圖將要輸出時,合併壓縮文件,使用替代文件輸出引用。

/*
 *添加js文件
 * @param $files array js文件地址數組
 */
function add_js_to_view($files)
{
    static $default_head_js = array();//定義靜態變量存儲添加的js文件
    $default_head_js = array_merge($default_head_js,$files);//合併已添加的文件

    $ci->view_data['default_head_js'] = $default_head_js;//將此靜態變量輸出到模板中使用(此行爲僞代碼)
    return;
}

/*
 * 壓縮js文件(同理可處理css文件)
 * 此處理過程爲:檢測配置文件中是否有過這些文件合併的壓縮文件,同時檢測資源的改變,
 * 
 * 模板中使用 echo compress_js($default_head_js) 輸出壓縮的文件
 * @param $arr array 需要壓縮的文件地址數組
 */
function compress_js($arr){
    if(!$arr && !is_array($arr)) return ;

    $base_url = dirname(BASEPATH).'/static/compress/';//壓縮文件存放目錄

    /*實例化壓縮類*/
    $yui = new yuicompressor(array(
        'java_home'=>'java', //或自己指定 jdk 安裝的 bin 目錄 (絕對路徑)
        'jar_file'=>$base_url.'yuicompressor-2.4.8.jar',
        'save_path'=>$base_url, //必須有可寫權限
        // -------- 全局設置 --------- //
        'charset'=>'utf-8', //文件的編碼
        'line-break'=>false, //在指定的列後插入一個 line-bread 符號
        // -------- javascript 代碼的配置選項 --------- //
        'nomunge'=>false,  //只是簡單壓縮,清除空行空格註釋等。
        'semi'=>false, //保留所有的分號
        'optimizations'=>false, //禁止優化代碼.
    ));

    $out_name = '';//最終js文件名
    $tag_new = true;//是否需要重新合併壓縮
    if(file_exists($base_url.'config.php')){//檢測配置文件是否存在
        $content = file_get_contents($base_url.'config.php');
        if($content != ''){//檢測配置文件裏的內容是否爲空
            $compress_config = json_decode($content,true);
            $config_key = '';//此合併文件的key
            foreach ($arr as $a){
                $config_key .= $a.'_';//拼接key值
            }
            if(isset($compress_config[$config_key])){//判斷此
                $tag = false;//記錄資源是否有變動
                foreach ($arr as $a){
                    @$filemtime = filemtime($a);//獲取文件上傳修改時間戳
                    if($compress_config[$config_key][$a]['time'] != $filemtime){
                        @unlink($compress_config[$config_key]['compress_name'].'.min.js');//刪除無用的文件
                        unset($compress_config[$config_key]);
                        $tag = true;//資源有變動,即資源上次更改時間戳有變化
                        break;
                    }
                }
                if($tag && file_exists('/static/compress/'.$compress_config[$config_key]['compress_name'].'.min.js')) {//如果資源無變動,並且文件存在,則使用次文件
                    $out_name = $compress_config[$config_key]['compress_name'];
                    $tag_new = false;
                }
            }
        }
    }

    if($tag_new){
        $config_key = '';
        $compress_name = 'index_'.time();//編譯文件名

        $compress_config[$config_key] = array();

        foreach ($arr as $a){
            $config_key .= $a.'_';
            file_put_contents($base_url.$compress_name.'.js',file_get_contents($a).";",FILE_APPEND);//合併所以文件
        }

        foreach ($arr as $a){
            @$compress_config[$config_key][$a]['time'] = filemtime($a);
        }

        $compress_config[$config_key]['compress_name'] = 'index_'.time();
        file_put_contents($base_url.'config.php',json_encode($compress_config));

        //對單個文件壓縮
        $resutlt = $yui->compress($base_url.$compress_name.'.js');
        $out_name =  $compress_config[$config_key]['compress_name'];
    }

    echo "<script src='" . base_url('/static/compress/'.$out_name.'.min.js') . "'></script>\r\n";//輸出壓縮後的js文件引用標籤
}

///*
// * 參考此類
// 
// 
// * PHP YUICompressor Class (Dual licensed under the MIT)
// * 風吟 (http://fengyin.name/guestbook.php)
// * DEMO http://sweet.fengyin.name/ (yui online compressor)
// ----------------------------------------------------------
// 要求: dk 1.4+  php exec() 
// 作用: 使用 yuicompressor 批量壓縮一個目錄的 js 或者 css 文件.也可以對單個文件進行壓縮
// ----------------------------------------------------------
// 
// //Windows 調用方式:
// 
//
//$yui = new yuicompressor(array(
// 'java_home'=>'java', //或自己指定 jdk 安裝的 bin 目錄 (絕對路徑)
// 'jar_file'=>'D:\www\htdocs\yuicompressor.jar', 
// 'save_path'=>'D:\www\htdocs\results\\', //必須有可寫權限
// // -------- 全局設置 --------- //
// 'charset'=>'utf-8', //文件的編碼
// 'line-break'=>false, //在指定的列後插入一個 line-bread 符號
// // -------- javascript 代碼的配置選項 --------- //
// 'nomunge'=>false,  //只是簡單壓縮,清除空行空格註釋等。
// 'semi'=>false, //保留所有的分號
// 'optimizations'=>false, //禁止優化代碼.
// ));
// 
// //對單個文件壓縮
// $resutlt = $yui->compress('D:\www\htdocs\swfobject_src.js');
// print_r ($resutlt);
// 
// //對目錄文件壓縮
// $resutlt = $yui->directory('D:\www\htdocs\\');
// print_r($resutlt);
// 
// ----------------------------------------------------------
// 
// //Linux  調用方式:
// 
// $yui = new yuicompressor(array(
// 'java_home'=>'java', //或自己指定 jdk 安裝的 bin 目錄 (絕對路徑)
// 'jar_file'=>'/home/admin/yuicompressor-2.4.2.jar', 
// 'save_path'=>'/home/admin/results/', //必須有可寫權限
// // -------- 全局設置 --------- //
// 'charset'=>'utf-8', //文件的編碼
// 'line-break'=>false, //在指定的列後插入一個 line-bread 符號
// // -------- javascript 代碼的配置選項 --------- //
// 'nomunge'=>false,  //只是簡單壓縮,清除空行空格註釋等。
// 'semi'=>false, //保留所有的分號
// 'optimizations'=>false, //禁止優化代碼.
// ));
// 
// //對單個文件壓縮
// $resutlt = $yui->compress('/home/admin/style.css');
// print_r ($resutlt);
// 
// //對目錄文件壓縮
// $resutlt = $yui->directory('/home/admin/');
// print_r($resutlt);
// 
// */
class yuicompressor {
    function __construct($options = array()) {
        $this->options = $options;
    }
    function args($o) {
        $jsargs = '';
        $line_break = '';
        $charset = '';
        $o['line-break'] && ($line_break = ' --line-break ' . $o['line-break'] . ' ');
        $o['charset'] && ($charset = ' --charset ' . $o['charset'] . ' ');
        $o['nomunge'] && ($jsargs .= ' --nomunge ');
        $o['semi'] && ($jsargs .= ' --preserve-semi ');
        $o['optimizations'] && ($jsargs .= ' --disable-optimizations ');
        $exten = $this->getExtension($o['file']);
        $cmd = array();
        $newfile = $o['save_path'] . $this->replace($o['file']);
        $cmd['file'] = $newfile;
        $cmd['shell'] = $o['java_home'] . ' -jar ' . $o['jar_file'] . ' --type ' . $exten['extension'] . $charset . $line_break . $jsargs . $o['file']. ' > ' . $newfile;
        return $cmd;
    }
    function getExtension($fn) {
        return pathinfo(strtolower($fn));
    }
    function replace($fn) {
        $exten = $this->getExtension($fn);
        return str_replace('.'.$exten['extension'], '.min.' . $exten['extension'], $exten['basename']);
    }
    function exec($cmd) {
        exec($cmd['shell'].' 2>&1',$out, $status);
        return array(
            'shell' => $cmd['shell'],
            'out' => implode("\n",$out),
            'status' => $status,
            'success' => $cmd['file']
        );
    }
    function ls($dir) {
        !($dh = opendir($dir)) && exit('open directory error');
        while (($file = readdir($dh)) !== false) {
            $exten = $this->getExtension($file);
            if ($exten['extension'] == 'js' || $exten['extension'] == 'css') {
                $files[] = $dir . $file;
            }
        }
        closedir($dh);
        return $files;
    }
    function directory($dir) {
        !is_dir($dir) && exit('directory error');
        foreach ($this->ls($dir) as $file) {
            $fn[] = $this->compress($file);
        }
        return $fn;
    }
    function compress($file) {
        $this->options['file'] = $file;
        return $this->exec($this->args($this->options));
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章