程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> 自己動手,豐衣足食.,自己動手豐衣足食

自己動手,豐衣足食.,自己動手豐衣足食

編輯:關於PHP編程

自己動手,豐衣足食.,自己動手豐衣足食


時下grunt非常的火啊,用著雖然很爽,但是它的配置確實很煩。如果之前沒有用過,想要一下子熟練駕馭它,有一定的學習成本,而且還要裝node這個大家伙,項目之初我們選擇了compiler.jar這個輕量的工具進行打包。我一直在尋思著,如何編寫一鍵打包工具。之前呢是手工的拼接好有的js文件,做成符合compiler.jar打包文件所要求的批處理文件,然後運行這個批處理,生成我們需要的js和css文件。隨著js文件數量的增長,純手工拼接這些文件的地址就變得非常考驗人的耐心了,而且還容易漏掉或重復某些文件,於是“一鍵打包工具”的編寫就變得刻不容緩了。下面是一個真實的index.html文件的一部分:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="target-densitydpi=device-dpi, initial-scale=1, user-scalable=0, maximum-scale=1">
     <!--隱藏浏覽器的工具欄和菜單欄,對iso系統起用-->
    <!--用於PC上調式,不參與合並壓縮-->
    <script src="lib/data/database.js" name="noBuild"></script>
    <!--Iframe加載處理-->
    <script src="lib/LoadMode.js"></script>

    <script src="lib/core/jQuery.js"></script>
    <script src="lib/core/underscore.js"></script>
    <script src="lib/animate/SVGIcons/snap.min.js"></script>
    <script src="lib/animate/pixi.js"></script>

    <script src="lib/core/Xut.js"></script>
    <script src="lib/core/isMobile.js"></script>
    <script src="lib/core/aaronRequire.js"></script>
    <script src="lib/core/nextTick.js"></script>
    <script src="lib/Config.js"></script>

    <script src="lib/core/lang/Object.js"></script>
    <script src="lib/core/lang/Function.js"></script>
    <script src="lib/core/lang/Array.js"></script>
    <script src="lib/core/video.js"></script>

    <!-- 自定義事件,合集處理,iframe通訊 -->
    <script src="lib/core/event/asEvented.js"></script>
    <script src="lib/core/message/pms.js"></script>

    <!--插件-->
    <script src="lib/plugin/cordova.js"></script>
    <script src="lib/plugin/readAssetsFilePlugin.js"></script>
    <script src="lib/plugin/initDatabase.js"></script>
    <script src="lib/plugin/web.js"></script>
    <script src="lib/plugin/video.js"></script>
    <script src="lib/plugin/openAppPlugin.js"></script>
    <script src="lib/plugin/tabletPlugin.js"></script>
    <script src="lib/plugin/statusbar.js"></script>
    <script src="lib/plugin/iap.js"></script>
    <script src="lib/plugin/AppStoreLink.js"></script>
    <script src="lib/plugin/downloadPlugin.js"></script>
    <script src="lib/plugin/xxteManager.js"></script>
    <script src="lib/plugin/unzipPlugin.js"></script>
    <script src="lib/plugin/readPlugin.js"></script>
    <script src="lib/plugin/deletePlugin.js"></script>
    <!-- 動畫庫 -->
    <script src="lib/animate/TweenMax.min.js"></script>
    <script src="lib/animate/plugins/ThrowPropsPlugin.min.js"></script>
    <script src="lib/animate/PptAnimation.js"></script>
    <script src="lib/animate/CanvasAnimation.js"></script>
    <script src="lib/animate/dragdrop/Draggable.min.js"></script>
    <script src="lib/animate/dragdrop/dragdrop.js"></script>
    <script src="lib/animate/iscroll.js"></script>
    <script src="lib/animate/hammer.js"></script>
    <script src="lib/animate/SVGIcons/svgicons-config.js"></script>
    <script src="lib/animate/SVGIcons/svgicons.js"></script>
    <script src="lib/animate/SpriteA.js"></script>

    <script src="lib/util/Utils.js"></script>
    <script src="lib/util/LocalStorage.js"></script>
    <script src="lib/util/ScriptLoad.js"></script>
    <script src="lib/util/ExecuteSql.js"></script>
    <script src="lib/util/PromptNotice.js"></script>
    <script src="lib/util/edge.js"></script>

    <!-- 配置文件,數據文件,結構文件 -->
    <script src="lib/data/Store.js"></script>
    <script src="lib/data/StoreManager.js"></script>

    <!-- 數據初始化 -->
    <script src="lib/Main.js"></script>
    <script src="lib/Initialize.js"></script>
    <script src="lib/scenario/SceneLayout.js"></script>
    <script src="lib/scenario/SceneFactory.js"></script>
    <script src="lib/scenario/SceneController.js"></script>
    <script src="lib/LoadScene.js"></script>
    <script src="lib/Dispatcher.js"></script>

    <!-- 工具欄 -->
    <script src="lib/toolbar/Navbar.js"></script>
    <script src="lib/toolbar/sToolbar.js"></script>
    <script src="lib/toolbar/fToolbar.js"></script>
    <script src="lib/toolbar/searchBar.js"></script>
    <script src="lib/toolbar/bookMark.js"></script>

    <!-- 多線程任務片 -->
    <script src="lib/threadTask/Buffer.js"></script>
    <script src="lib/threadTask/TaskContents.js"></script>
    <script src="lib/threadTask/TaskComponents.js"></script>
    <script src="lib/threadTask/TaskBackground.js"></script>
    <script src="lib/threadTask/TaskContainer.js"></script>

    <script src="lib/pageBase/Parser.js"></script>
    <script src="lib/pageBase/Collection.js"></script>
    <script src="lib/pageBase/MultiEvent.js"></script>
    <script src="lib/pageBase/PageBase.js"></script>
    <script src="lib/pageBase/Page.js"></script>
    <script src="lib/pageBase/Master.js"></script>


    <!-- 頁面管理模塊 -->
    <script src="lib/controller/transform/Translation.js"></script>
    <script src="lib/controller/OverrideApi.js"></script>
    <script src="lib/controller/Abstract.js"></script>
    <script src="lib/controller/Emitter.js"></script>
    <script src="lib/controller/PageMgr.js"></script>
    <script src="lib/controller/MasterMgr.js"></script>
    <script src="lib/controller/Compiler.js"></script>
    <script src="lib/controller/ViewModel.js"></script>
    <script src="lib/controller/SwitchPage.js"></script>
    <script src="lib/controller/EventDrive.js"></script>

    <!--熱點管理-->
    <script src="lib/scheduler/AssignAutoRun.js"></script>
    <script src="lib/scheduler/AssignTrigger.js"></script>
    <script src="lib/scheduler/AssignSuspend.js"></script>
    <script src="lib/scheduler/AssignOriginal.js"></script>
    <script src="lib/scheduler/AssignRecovery.js"></script>
    <script src="lib/scheduler/ProcessControl.js"></script>
    <script src="lib/scheduler/Binding.js"></script>

    <!-- 適配器,用於處理熱點 -->
    <script src="lib/directives/dir-Content.js"></script>
    <script src="lib/directives/dir-Widget.js"></script>
    <script src="lib/directives/dir-Media.js"></script>
    <script src="lib/directives/dir-Action.js"></script>
    <script src="lib/directives/dir-ShowNote.js"></script>

     <!--多媒體對象 -->
    <script src="lib/component/media/Audio.js"></script>
    <script src="lib/component/media/Video.js"></script>
    <script src="lib/component/media/AudioManager.js"></script>
    <script src="lib/component/media/VideoManager.js"></script>

    <!--文本熱點-->
    <script src="lib/component/content/conFilter.js"></script>
    <script src="lib/component/content/conAlgorithm.js"></script>

後面還有很長,bug,活人不能被尿憋死,辦法總比問題多。我是會一點php的,php在處理文件方面是很拿手的,是時候讓它發揮點作用了。於是我想到了用php去自動提出index裡邊的js和css,然後按指定的格式生成批處理文件,在後台用靜默方式運行這個批處理,最後把結果返回給顯示器。這樣我就可以坐享其成了。想想都有點小激動喲,於是簡單的寫了一個界面.

 

接下來就是實現功能了,先不著急編寫代碼,分析下需求:

1. 遍歷index.html文件,提取js文件或css文件.

2. 對這文件進行過慮,因為有些是注釋掉的,有些是調式用的。

3. 生成對應的批處理文件

4. 執行批處理文件

5. 顯示處理結果

即然有兩種情況,我就用一個工廠模式來適配,方便以後擴展其它類型,目光要放長遠一點。即然工廠都有了,那索性再來一個接口,約定都必需要實現“接收請求”和“輸出結果”這兩個接口。再想想處理js和css都可能會有相同的功能,讓它們繼承一個父類可以使代碼復用,於是繼承也先用上。目前的設計應當可以滿足我的要求了,於是開始編寫php代碼.

<?php
header("Content-type: text/html; charset=utf-8");

/**
 * 根據index.html文件中引用的js,生成compressJs.bat
 * @author frog <[email protected]>
 * @date 2014-11-17
 */

interface ICompress {
    /**
     * 處理用戶請求
     * @return [type] [description]
     */
    public function request();

    /**
     * 處理輸出結果
     * @return [type] [description]
     */
    public function render();
}

class BaseCompress {
    public $content;
    public $outPath;
    public $isAuto;

    public function __construct($isAuto=false){
        $outPath = '_file';
        if(!is_dir($outPath)){
            mkdir($outPath);
        }
        $this->outPath = $outPath;
        $this->isAuto = $isAuto;
    }


    /**
     * 運行批處理
     * @return [type] [description]
     */
    public function runBat($name){

    }
}

/**
 * 壓縮javascript文件
 * 合並javascript文件
 */
class CompressJS extends BaseCompress implements ICompress {

    /**
     * 處理用戶請求
     * @return [type] [description]
     */
    public function request(){

    }

    /**
     * 處理輸出結果
     * @return [type] [description]
     */
        public function render(){}

}

/**
 * 壓縮樣式文件
 */
class CompressCSS extends BaseCompress implements ICompress {

    public function request(){
 
    }

    /**
     * 處理輸出結果
     * @return [type] [description]
     */
         public function render(){}
     
}

/**
 * 工廠類
 */
class Factory {

    public static function create($type,$isAuto){
        $ob = null;
        switch ($type) {
            case 'js':
                $ob = new CompressJS($isAuto);
                break;
            case 'css':
                $ob = new CompressCSS($isAuto);
                break;
            default:
                # code...
                break;
        }
        return $ob;
    }
}

然後是調用處理:

//處理ajax請求
if(isset($_POST['submit'])){
    //是否自動執行批處理
    $isAuto = $_POST['zip'] === 'true' ? true : false;
    //處理類型
    $type = $_POST['type'];

    $c = Factory::create($type,$isAuto);
//接口方法 $c->request(); $c->render(); }else{ echo '請使用靜態頁訪問本程序:<a href="index.html">點此進入</a>'; }

大致的骨架就出來了。具體的填碼過程就比較簡單了。稍微有點難度的就是執行批處理這個一方法.

是網上提供的方法,以後可能用的上,這裡特意貼一下:

public function runBat($name){
        if(!file_exists($name) || !$this->isAuto){
            return;
        }
        //轉入後台處理
        @exec(pclose(popen("start /B ". escapeshellcmd($name), "r")));
    }

在前面的index.html中,有一個name="noBuild"這個是我人為添加的,這是因為我要過濾這種標識的js文件,這樣以後要過濾別的文件,也只要添加這個標識就可以了,不用改php代碼。由於是內部使用,沒有做表單項來指定工程的路徑,默認就是index.html所處的上級目錄即為工程目錄。這樣設計簡化了操作,提高了效率。

關於遍歷特定的文件,我推薦glob函數,很簡潔的方案:

$files = glob($path.'/*.css',GLOB_NOSORT);

下面是工程目錄結構圖:

再來一張運行效果圖:

  

最後是處理結果圖:

終於不用寫grunt的配置和安裝node這個家伙了,再也不擔心更新的時候,從svn上拉下來一堆node的東西,是時候和它們說再見了:

好像忘了展示前端代碼了:

/**
 * 選項卡類
 * @param {string} id 選項卡的ID
 */
function Tabs(id){
    var node = document.querySelector('#'+id);
    var selected = node.querySelector('.selected');
    this.selected = selected;
    this.node = node;
    this.bindEvent();
}

/**
 * 切換選項卡
 * @param  {object} event 事件
 * @return {[type]}   [description]
 */
Tabs.prototype.change = function(event){
    var element = event.target;
    if(element.tagName.toLowerCase()=='li'){
        if(element.className=='selected'){
            return;
        }
    }else{
        while(element != this.node){
            element = element.parentNode;
            if(element.tagName.toLowerCase()=='li'){
                break;
            }
        }
        if(element == this.node) return;
    }
    this.selected.removeAttribute('class');
    element.className = 'selected';
    this.selected = element;
    this.content();
}

Tabs.prototype.content = function(){
  var form = document.form1;

    switch(this.getTabType()){
      case 'js':
        form.style.display = 'block';
        form.children[0].innerHTML = '自動壓縮JS';
        break;
      case 'css':
        form.style.display = 'block';
        form.children[0].innerHTML = '自動壓縮CSS';
        break;
      default:
    }
}

 

會前端和後端,就是這麼任性。輕輕一點,告別煩惱!造自己的工具,讓別人去苦逼吧,So easy!

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved