日期:2014-05-16  浏览次数:20338 次

优化EXTJS的按模块下载JS的功能
最近有不少用户跟我反馈,访问Joffice页面的某些功能,需要等几秒钟才能出来。鉴于这种情况,在此分析一下原因,同时也给出一些解决方案,可以帮助Joffice 1.2,Joffice 1.3的开发用户解决这种根本的问题,可以让这种按模块下载js速度提高7-8倍,特别是有一些模块需要加载很多js的时候,其下载速度还高更多。



joffice 1.3以前的版本,按模块下载的原理如下:

在此我们以流程管理模块为例:



在App.import.js中定义该模块所依赖的js,如下:

   
FlowManagerView:[  
                __ctxPath+'/js/flow/ProTypeForm.js',  
                __ctxPath+'/js/flow/ProDefinitionForm.js',  
                __ctxPath+'/js/flow/ProDefinitionView.js',  
                __ctxPath+'/js/flow/FlowManagerView.js',  
                __ctxPath+'/js/flow/ProDefinitionDetail.js',  
                __ctxPath+'/js/flow/ProcessRunStart.js',  
                __ctxPath+'/js/flow/ProDefinitionSetting.js',  
                __ctxPath+'/js/flow/MyTaskView.js',  
                __ctxPath+'/js/flow/ProcessNextForm.js',  
                __ctxPath+'/js/flow/FormDesignWindow.js',  
                __ctxPath+'/js/flow/FormEditorWindow.js',  
                __ctxPath+'/js/flowDesign/FlowDesignerWindow.js'  
        ]
 
在此可以看出,该模块所依赖的js比较多,不过每个js都不大。

当点击左菜单的“流程管理”时,其就通过ScriptMgr来下载其所依赖的js,全部下载完成后,才创建这个流程管理的Panel,并且加到TabCenterPanel中去。



我们的调用下载的js代码如下:

function $ImportJs(viewName,callback,params) {  
    var b = jsCache[viewName];  
      
    if (b != null) {  
        var view =newView(viewName,params);  
        callback.call(this, view);  
    } else {  
        var jsArr = eval('App.importJs.' + viewName);  
        if(jsArr==undefined || jsArr.length==0){  
            try{  
                var view = newView(viewName,params);  
                callback.call(this, view);  
            }catch(e){  
            }  
            return ;  
        }  
        ScriptMgr.load({  
                    scripts : jsArr,  
                    callback : function() {  
                        jsCache[viewName]=0;  
                        var view = newView(viewName,params);  
                        callback.call(this, view);  
                    }  
        });  
    }  
}


即我们调用:
$ImportJs('FlowManagerView',function(){  
      return new FlowManagerView();  
});

当传入FlowManagerView时,告诉我们就是需要在App.Import.js中取出该依赖的js数组,然后传给ScriptMgr的load中的scripts参数,告诉他们我们要完成这些js的加载,并且完成后,创建FlowManagerView对象。



现在我们来看一下ScriptMgr的Load方法:
ScriptLoaderMgr = function() {  
    this.loader = new ScriptLoader();  
  
    this.load = function(o) {  
        if (!Ext.isArray(o.scripts)) {  
            o.scripts = [o.scripts];  
        }  
  
        o.url = o.scripts.shift();  
  
        if (o.scripts.length == 0) {  
            this.loader.load(o);  
        } else {  
            o.scope = this;  
            this.loader.load(o, function() {  
                        this.load(o);  
                    });  [size=medium][/size]
        }  
    };  
};

ScriptLoader的代码如下:
/** 
 * 用于动态加载js 
  *  sample is here 
  *   ScriptMgr.load({ 
  *   scripts: ['/js/other-prerequisite.js', '/js/other.js'], 
  *   callback: function() { 
  *     var other = new OtherObject(); 
  *     alert(other); //just loaded 
  *   } 
  * });  
  */  
ScriptLoader = function() {  
    this.timeout = 10;  
    this.scripts = [];  
    this.disableCaching = true;//false  
    this.loadMask = null;  
};  
  
ScriptLoader.prototype = {  
    showMask : function() {  
        if (!this.loadMask) {  
            this.loadMask = new Ext.LoadMask(Ext.getBody());  
            this.loadMask.show();  
        }