Sencha Touch 手機移動開發框架 HTML5 項目壓縮方案;

Sencha Touch框架生成基本項目目錄結構javascript

Index.html/
App.js
App.json
/touch[sdk]/
        /Sencha-touch.js
        /src
Resources/
App/

app.js以及app.json 是程序的入口點及基本加載配置;html

/touch[sdk]java

  sencha-touch[debug|min...].js 是 SDK 文件node

  /src 這裏是存放組件的位置git

Resources/用於存放 樣式及圖片等資源文件;github

app/用於存放咱們編寫的程序源碼;npm

壓縮優化目標json

把app/ , app.js , sdk[touch/sencha-touch.js], components[touch/src]分開壓縮數組

再對app/ 各自模塊進行壓縮! 服務器

Sencha Touch compile編譯研究

>sencha compile \
>[-cl=touch/src,app] //這個沒必要寫,否則生成出來的文件,會很大,估計是重複拼接的緣由.
>-ig=app.js,app/view //這裏能夠寫文件,或是文件夾均可以
>concat –yui jsoutfile.js

以上須要具備 Sencha touch 編譯命令行環境下運行;

按需加載壓縮方式:

獲取依賴組件命令:

sencha compile –cl=touch/src,app meta –filenames –out filenames.txt

將獲取的列表中把 app.js, app/下全部腳本去除;

採用 YUI Compressor加密壓縮這些dependencies文件合併後的文件; 採用批處理命令先合併爲一個大文件;

Union.bat

@echo off  
set /p outFile=請填寫輸出文件名:  
set /p fList=請填寫合併列表文件:  
for /f %%i in (%fList%) do (
    for /f "delims=" %%j in (%%i) do echo %%j >> %outFile%
)
java -jar D:\software\YUI-Compass\yuicompressor-2.4.2\build\yuicompressor-2.4.2.jar --type js --charset utf-8  %outFile%  -o %outFile%

這種方法,會出現漢字亂碼,會出現雙引號異常.

//修改

要不出現亂碼,及雙引號問題,只能copy命令:

Copy命令能夠拷貝其餘文件夾的文件, 但只支持 \ 的路徑, [/這種不支持];

for /f "delims=" %%j in (%%i) do echo %%j >> %outFile%
###改成:
copy "%outFile%"+"%%i" %outFile%

但這樣也會出現一些特殊的符號出來,須要手動改掉;

這種狀況下,按需合併的結果爲 788KB , 原來有 2956KB [1/4]; 這是除 app.js 以及 app/ 下腳本的壓縮結果;

把壓縮後的文件, 放在sdk [sencha-touch.js] 之下

發現有錯誤, sencha-touch.js加載後,會默認的引用touch/src下的一些必須依賴文件;

 

在文件中若是使用到類型Ext.xxx.Component的地方,默認的加載方式仍是爲/touch/src/xx/xx 這樣的地址;

想要把組件+SDK與咱們寫的app文件夾腳本以及app.js分開,這種方式有點困難!

Touch/src下全壓縮方式

其實按需壓縮,對於一個差很少點大的項目,所使用到依賴組件都幾本上都用到,整個touch/app組件庫是3M左右,按需獲取的依賴文件也是3M左右。

因此能夠壓縮全部組件來使用。

使用grunt=> /touch/src全壓縮方式,不採用依賴方式

Concat: {
        Dist: {
            Src:’build/**/*.js’,
            Dest:’build/components.js’
        }
},
Uglify: {
        Build: {
            Src:’build/components.js’,
            Dest:’build/components.min.js’
        },
        Dist: {
            Files: {
                ‘build/sencha.min.js’:’touch/sencha-touch.js’
            }
        }
} 

Concat 看字就能夠知道是什麼意思,他表示聯合起來的意思,這裏是把腳本文件都聯接起來,/build/**/*.js 表示 build 下的全部文件;

Dist 能夠不用管,這是一個自定義的詞,表示一個要執行的任務名稱;

src表明腳本文件,或集合;

Dest: 'build/components.js' ; 表示把 src 集合 聯接成 未壓縮的 components.js 文件;

Uglify 表示壓縮配置;

下面有兩個任務:build, Dist;

build 的任務是把 上面聯合起來的文件 components.js 壓縮成 components.min.js;

Dist 下的 Files 能夠配置多個執行項,是個 json 格式數據;Files:{outfile: file}, 把Value 代碼的文件,壓縮成 key 所指定的 outfile;

這樣壓縮出來的組件文件 components.min.js 大小爲: 760kb,sdk文件sencha.min.js爲122kb;

建立 grunt-Sencha_ZOrderCompress 插件過程;

按順序壓縮指定Sencha加載的腳本文件, 能夠選擇多種模式壓縮;

grunt-sencha-zordercompress分按需壓縮與全壓縮兩種方式;

每種方式下又能夠分:

  1. APP_APPJS_ADKCOMS : 壓縮兩份: apps/下的文件, 以及 sdk+components的文件
  2. APP_APPJS_ADK_COMS : 壓縮三份 : apps/下的文件, 以及 sdk文件 和 components文件三部分.
  3. 每種模式均可以全壓縮

全部配置出來的可壓縮項爲:

全壓縮: '<%=Sencha_ZOrderCompress_dist%>'

組件或組件加sdk: '<%=Sencha_ZOrderCompress_dist_ext_core%>'

apps/下文件壓縮: '<%=Sencha_ZOrderCompress_dist_apps%>';

詳見:https://github.com/gloot/grunt-sencha-zordercompress

1. grunt 命令行 轉到項目根目錄 /node_modules 下;

2. 使用 

npm install –g grunt-init

安裝grunt-init;

3. 第二安裝github工具.

 Git,Windows下的Git,地址:http://msysgit.googlecode.com/files/Git-1.7.9-preview20120201.exe

 git、CopSSH安裝能夠參照(注意:看圖片就行了其它的無視): http://www.codeproject.com/Articles/296398/Step-by-Step-Setup-Git-Server-on-Windows-with-CopS ;

 這樣就能夠了,CopSSH能夠不用安裝;

 再用  執行:

git clone git://github.com/gruntjs/grunt-init-gruntplugin.git ~/.grunt-init/gruntplugin

4. 安裝gruntplugin模板

轉到目標項目根目錄,若是已經存在node_modules,就轉到node_modules下;

>md 項目文件夾名[grunt-sencha-zorderCompress]

>cd grunt-sencha-zorderCompress

>grunt-init gruntplugin #[在這個文件下建立grunt插件模板]# 

接下來是作些配置,最後生成一個標準的 grunt 插件模板;

5. 接下來給 grunt-sencha-zorderCompress 插件內再添加輔助插件 [自動生成node_modules] 

>Npm install grunt-lib-phantomjs
>Npm install phantomjs #[會生成phantomjs與.bin文件夾]# >Npm install connect

在package.json添加dependencies節點 包含上面三個插件;

"dependencies": {
    "grunt-lib-phantomjs": "~0.4.0",
    "phantomjs": "1.9.2-1",
    "connect": "~2.9.0"
  },

生成結構:

剛纔配置的項目名爲: Sencha_ZOrderCompress

模板生成後會在 grunt-sencha-zorderCompress/task 下生成一個 Sencha_ZOrderCompress.js 文件;

內容大概爲:

‘use strict’;

Module.exports = function(grunt) {
        Grunt.registerMultiTask(‘Sencha_ZOrderCompress’, ‘plug description’, function() {
            //do…
            //在這裏有 方法內的 this對象.
            //能夠運行[gruntfile.js] grunt.registerTask (‘xxx’, [‘Sencha_ZOrderCompress’]);
            //所指定節點的數據
    });
};

這裏的gruntfile.js裏 Sencha_ZOrderCompress 的配置爲:

GetSenchaOrderAllComponents: {
        dist: {
            options: {
                appJs : ‘app.js’,
                processHtml:’index.html’
            }
        }
}

那麼. Sencha_ZOrderCompress.js 的 Grunt.registerMultiTask 內,就能夠獲取 options的配置項:

Var options = this.options({});

Sencha_ZOrderCompress.js 代碼:

/*
 * Sencha_ZOrderCompress
 * http://www.cmszu.com
 *
 * Copyright (c) 2013 Gloot/ZWD
 * Licensed under the MIT license.
 */

'use strict';

var path = require("path"),
    depenconfig = require(__dirname + path.sep + 'sencha_grunt_set.js'),
    depenHolder = require(__dirname + path.sep + 'sencha_phantomjs_holder.js'),
    allcomponents = [];

module.exports = function(grunt) {

  // Please see the Grunt documentation for more information regarding task
  // creation: http://gruntjs.com/creating-tasks
  function getOptions(instance) {
      return instance.options({});
  }

  function setOtherComponentsInOrder(files) {
      for (var i=0; i<allcomponents.length; i++)
      {
          var hasIn = false;
          var jspath = allcomponents[i];
          for (var j=0; j<files.length; j++)
          {
              if (jspath.toLowerCase() == files[j].toLowerCase())
              {
                  hasIn = true;
                  break;
              }
          }

          if (hasIn == false)
          {
              //grunt.log.writeln('Else files: ' + jspath);
              files.push(jspath);
          }
      }

      return files;
  }

  grunt.registerMultiTask('Sencha_ZOrderCompress', 'Compress compile sencha by order Loaded javascript files!', function() {
    // Merge task-specific and/or target-specific options with these defaults.
    var me = this,
        options = getOptions(me),
        done = me.async();

    grunt.log.writeln( 'Start Task: === Sencha_ZOrderCompress' );
    
    var holder = new depenHolder(options.processHtml, options.appName, options.mode, options.compassAll);
    holder.setGrunt(grunt);

    me.files.forEach(function(f) { //important
        var coms = f.src.filter(function(filepath) {
            //grunt.log.writeln('component files: ' + filepath);
            allcomponents.push(filepath);
        });
    });
    var usecoms = options.compassAll ? allcomponents : [];
    
    holder.getDependencies(function(files, sencha) {
        
        grunt.log.writeln( 'Task Target:===================================' + me.target); //out dist

        depenconfig(files, grunt, 'Sencha_ZOrderCompress_'+me.target, options.mode, sencha, options.moduFunc);
        done();
    }, usecoms);
  });

};

要想像下面的調用腳本方法:

depenconfig = require(__dirname + path.sep + 'sencha_grunt_set.js'),
depenHolder = require(__dirname + path.sep + 'sencha_phantomjs_holder.js'),

腳本文件,就須要 若是下的寫法:

//腳本必須爲:
//1 形式:
Module.exports = function(aaa,bbb,..) {
        
}

//2 形式:
Function afuncName(aaa,bbb,…) {
}
Module.exports = afuncName;

//3 形式:
Function classfunc(aaa, bbb,…) {
        This.aaa = aaa;
        ….
}

classfunc.prototype.method = function() {
}

Module.exports = classfunc;

require 才能這樣加載一個腳本文件;(grunt模塊|插件|中間件)可以使用:var xxxx = require(__dirname + path.sep + 腳本文件來獲取);

Grunt 須要瞭解一些知識跟經常使用組件;

1>. 瞭解 Nodejs Path模塊: var path = require(‘path’);

  http://lnmp.in/nodejs-path 路徑拼接組合,返回標準化的路徑;

2>. 瞭解 Nodejs connect模塊: var connect = require(‘connect’);

  輕量級架設服務器的Nodejs中間件組件.

  http://deadhorse.me/nodejs/2011/11/26/nodejs_connect_analysis_1.html 

3>. 在 gruntfile.js 部分:

Grunt.initConfig({
        TaskName : {
            Dist: {
                //xxxx
            }
        }
});

其下有src/dest等屬性

Src 爲配置的文件路徑, 該路徑可正則匹配全部的文件

/*.js 表明某文件夾下的全部.js文件

/**/*.js 表明某文件夾及其全部子文件夾下的全部.js文件

 

返回全部文件數組爲:

this.files.forEach(function(f) {

            var files = f.src.filter(function(filepath) {

                     //filepath即爲src設定下的文件列表的其中一個文件.

            });

});    

 

Dist下的配置項能夠經過若是方式獲取:

這裏是options:

//這是在 TaskName 所在文件 TaskName.js的 grunt.registerMultiTask 裏

Var options = instance.options({}); //能夠instance.options的json部分再添加字段屬性.

TaskName.js 即爲上面 Sencha_ZOrderCompress.js 文件;

設置值: 

在 gruntfile.js 裏有:

Concat : {
        Dist: {
            Src : ‘<%= taskName_xxx %>’
        }
}

這個taskName_xxx 的值 可由 :

Grunt.config.set(‘taskName_xxx’, valueobj);

來配置,通常爲數組;

Concat爲組合由src設定的文件列表組合文件;

Uglify 爲壓縮插件, src爲源數據文件, dest爲壓縮結果文件:

Uglify: {
        Build: {
            Src:’’,
            Dest:’’
        }
}
Dist : {
        Files: {
            ‘壓縮文件地址’, ‘源文件地址’
                }
}

Grunt.registerTask(‘default’, []); //default爲默認必須任務配置項;

Nodejs在這裏有不少模塊,中間組須要學習.

Fs, connect, path等.

1>. Connect中間件, 在指定文件下建立服務與端口:

Var app = connect().use(connect.static(process.cwd())).listen(3000);

Process爲內置對象, 可直接使用.

Process.cwd() 獲取當前 Nodejs命令行操做所在的當前目錄.

Connect.static(這裏應該能夠自定義一個地址)

另寫法: connect[‘static’](地址);

//關閉服務

App.close();

2>. file copy write 等;

Grunt.log.writeln|error|warn|debug…
Grunt.file.copy|delete|write

copy:

Grunt.file.copy(copyfrompath, copyTopath, {
        Process: function(contstring) {
            //contstring即爲copyfrompath所在文件內容
            //return contstring纔可保存到copyTopath文件.
        }
});

write:

Grunt.file.write(‘文件地址’, ‘文件內容’);

3>. Phantomjs部分

Phantomjs.on(‘onResourceRequested’, function(response) {
        //response.url
        //執行摸擬文件初始時加載的文件.
        //驟步輸出
});

Phantomjs.on(‘error.onError’, function(msg, tracer) {
        //執行加載發生異常時輸入
});

Phantomjs.on(‘mytask.done’, function(findfiles) {
        Files = findfiles.history;
        Phantomjs.halt();
});
//mytask.done爲自定義響應事件.

在grunt-lib-phantomjs插件/phantomjs/main.js內

setInterval(function() {
        //在執行到timeout後,獲取響應結果的文件是sendMessage輸出.
});

Phantomjs.on(‘fail.load’, function(url) {
        //加載失敗
        Phantomjs.halt();
});

Phantomjs.on(‘fail.timeout’, function() {
        //超時
        Phantomjs.halt();
});

Phantomjs.spawn(‘由connect建立的服務下地摸擬執行文件地址(url)’, {
        Options: { //引用事件響應文件
            phantomScript: ‘grunt-lib-phantomjs插件下/phantomjs/main.js所在位置’,
              loadImages : false
        },
        Done: function(err) {
            //返回文件數組結果
            //刪除相應的文件
            //關閉服務
        }
});

Sencha相關研究結果:

Sencha頁面初始化,須要加載相應的sencha components組件文件,並且要按必定的順序排序,否則會出現,組件內引用另組件不存在的狀況,這裏他會默認到/touch/src下加載相應的文件所在位置.

因此若是要壓縮全部的組件,就要把全部的組件加載到 Sencha Ext.application內的requires下,模擬運行初始化操做,這樣,sencha核心加載會按順序加載所需的文件。才能壓縮到全部sencha components!

研究發現, Ext.device加載處理得很差, 實際上在debug模式下是沒有Ext.device部分代碼的,因此在全壓縮模式下去除了Ext.device部分代碼;

相關文章
相關標籤/搜索