zoukankan      html  css  js  c++  java
  • Sencha Touch 手机移动开发框架 HTML5 项目压缩方案;

    Sencha Touch框架生成基本项目目录结构

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

    app.js以及app.json 是程序的入口点及基本加载配置;

    /touch[sdk]

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

      /src 这里是存放组件的位置

    Resources/用于存放 样式及图片等资源文件;

    app/用于存放我们编写的程序源码;

    压缩优化目标

    把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:softwareYUI-Compassyuicompressor-2.4.2uildyuicompressor-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部分代码;

  • 相关阅读:
    实验四 代码评审
    UML 建模工具的安装与使用
    结对编程(阶段二)
    结对编程第一阶段
    实验一 GIT 代码版本管理
    【Alpha冲刺阶段】Scrum Meeting Daily5
    【Alpha冲刺阶段】Scrum Meeting Daily2
    个人项目作业
    个人介绍+软工5问
    SpringMVC拦截html页面访问
  • 原文地址:https://www.cnblogs.com/editor/p/4049957.html
Copyright © 2011-2022 走看看