GWT生成JavaScript代码文件分析

    GWT生成javascript后,WWW目录中会得到很多HTML和JS代码。这些代码的作用是什么对于每一个初次使用GWT的人来说,都会有这样的困惑。下面我将对这些文件的大概作用进行以下简单的说明,并对其中的部分JS进行分析。
    首先说一下会生成哪些文件。以下是文件的列表。这个列表只包括HTML,和JS文件。这些文件都是单个GWT module编译后产生的。本文使用的原代码来自GWT论坛。如果想得到完全相同的文件列表,读者可以自行下载。
下载地址是: http://www.mooreds.com/files/mtgcalc-v1.tar.gz

文件列表:

1、MortgageCalc.html
2、gwt.js
3、history.html
4、com.cohomefinder.gwt.mortgagecalculator.MortgageCalc.nocache.html
5、31B37A91E12073356EFED6A87DDD05BB.cache.html
6、992FF46E12A7705BC86ACDF2A5956B7C.cache.html
7、BC136B40572B863559384961791144CA.cache.html
8、77A54215924094616B0083B14A757399.cache.html

这些都是些什么文件呢?下文将逐一介绍。

MortgageCalc.html


    这个文件不用多说了,就是要插入编译后JS的目标HTML。GWT的JS插入不是在编译时进行的,而是在运行时由GWT定义的JS进行运行时插入。所以查看host page的源文件时只能看到以下内容:
< meta  name ='gwt:module'  content ='com.cohomefinder.gwt.mortgagecalculator.MortgageCalc' >
< script  language ="javascript"  src ="gwt.js" ></ script >
   其中动态加载代码就在gwt.js中,而meta数据提供了必要的信息,帮助动态加载文件选择正确的代码加载。

gwt.js:

    这就是上面所说提到的文件。里面的代码主要是用来动态加载编译后的JS代码的。这10页的JS代码中,一共定义了3个类:DynamicResources,ModuleControlBlock, ModuleControlBlock。
//
//
 DynamicResources
//

function  DynamicResources()  {
  
this.pendingElemsBySrc_ = {};
  
this.pendingScriptElems_ = new Array();
}

DynamicResources.prototype 
=   {} ;

//  The array is set up such that, pairwise, the entries are (src, readyFnStr).
//
 Called once for each module that is attached to the host page.
//
 It is theoretically possible that addScripts() could be called reentrantly
//
 if the browser event loop is pumped during this function and an iframe loads; 
//
 we may want to enhance this method in the future to support that case.
DynamicResources.prototype.addScripts  =   function (scriptArray, insertBeforeElem)  {
  
var wasEmpty = (this.pendingScriptElems_.length == 0);
  
var anyAdded = false;
  
for (var i = 0, n = scriptArray.length; i < n; i += 2{
    
var src = scriptArray[i];
    
if (this.pendingElemsBySrc_[src]) {
      
// Don't load the same script twice.
      continue;
    }

    
// Set up the element but don't add it to the DOM until its turn.
    anyAdded = true;
    
var e = document.createElement("script");
    
this.pendingElemsBySrc_[src] = e;
    
var readyFn;
    eval(
"readyFn = " + scriptArray[i+1]);
    e.__readyFn 
= readyFn;
    e.type 
= "text/javascript";
    e.src 
= src;
    e.__insertBeforeElem 
= insertBeforeElem;
    
this.pendingScriptElems_ = this.pendingScriptElems_.concat(e);
  }

  
  
if (wasEmpty && anyAdded) {
    
// Kickstart.
    this.injectScript(this.pendingScriptElems_[0]);
  }

}


DynamicResources.prototype.injectScript 
=   function (scriptElem)  {
  
var parentElem = scriptElem.__insertBeforeElem.parentNode;
  parentElem.insertBefore(scriptElem, scriptElem.__insertBeforeElem);
}


DynamicResources.prototype.addStyles 
=   function (styleSrcArray, insertBeforeElem)  {
  
var parent = insertBeforeElem.parentNode;
  
for (var i = 0, n = styleSrcArray.length; i < n; ++i) {
    
var src = styleSrcArray[i];
    
if (this.pendingElemsBySrc_[src]) 
      
continue;
    
var e = document.createElement("link");
    
this.pendingElemsBySrc_[src] = e;
    e.type 
= "text/css";
    e.rel 
= "stylesheet";
    e.href 
= src;
    parent.insertBefore(e, insertBeforeElem);
  }

}


DynamicResources.prototype.isReady 
=   function ()  {
  
var elems = this.pendingScriptElems_;
  
if (elems.length > 0{
    
var e = elems[0];
    
if (!e.__readyFn()) {
      
// The pending script isn't ready yet.
      return false;
    }

    
    
// The pending script has now finished loading. Enqueue the next, if any.
    e.__readyFn = null;
    elems.shift();
    
if (elems.length > 0{
      
// There is another script.
      this.injectScript(elems[0]);
      
return false;
    }

  }


  
// There are no more pending scripts.
  return true;
}
    这个类主要的功能是向host page中插入一些JS和CSS。

//
//
 ModuleControlBlock
//
function  ModuleControlBlock(metaElem, rawName)  {
     
var parts = ["", rawName];
  
var i = rawName.lastIndexOf("=");
  
if (i != -1{
    parts[
0= rawName.substring(0, i) + '/';
    parts[
1= rawName.substring(i+1);
  }


  
this.metaElem_ = metaElem;
  
this.baseUrl_ = parts[0];
  
this.name_ = parts[1];
  
this.compilationLoaded_ = false;
  
this.frameWnd_ = null;
}

ModuleControlBlock.prototype 
=   {} ;

/**
 * Determines whether this module is fully loaded and ready to run.
 
*/

ModuleControlBlock.prototype.isReady 
=   function ()  {
  
return this.compilationLoaded_;
}
;

/**
 * Called when the compilation for this module is loaded.
 
*/

ModuleControlBlock.prototype.compilationLoaded 
=   function (frameWnd)  {
    alert(frameWnd);
  
this.frameWnd_ = frameWnd;
  
this.compilationLoaded_ = true;
}


/**
 * Gets the logical module name, not including a base url prefix if one was
 * specified.
 
*/

ModuleControlBlock.prototype.getName 
=   function ()  {
  
return this.name_;
}


/**
 * Gets the base URL of the module, guaranteed to end with a slash.
 
*/

ModuleControlBlock.prototype.getBaseURL 
=   function ()  {
  
return this.baseUrl_;
}


/**
 * Gets the window of the module's frame.
 
*/

ModuleControlBlock.prototype.getModuleFrameWindow 
=   function ()  {
  
return this.frameWnd_;
}


/**
 * Injects a set of dynamic scripts.
 * The array is set up such that, pairwise, the entries are (src, readyFnStr).
 
*/

ModuleControlBlock.prototype.addScripts 
=   function (scriptSrcArray)  {
    alert(scriptSrcArray);
  
return ModuleControlBlocks.dynamicResources_.addScripts(scriptSrcArray, this.metaElem_);
}


/**
 * Injects a set of dynamic styles.
 
*/

ModuleControlBlock.prototype.addStyles 
=   function (styleSrcArray)  {
  
return ModuleControlBlocks.dynamicResources_.addStyles(styleSrcArray, this.metaElem_);
}

    一个
ModuleControlBlock的实例描述了一个gwt模块的信息。一个host page可以载入并运行多个gwt模块, 每个 gwt模块都会用一个 ModuleControlBlock来描述 。gwt模块都有一个名字来区分,模块的名字就是java源代码中的java类的fullly qualified class name(完整类名)。
    模块在编译后,会生成一个与模块名字对应的,以nocache.html结尾的一个HTML文件。在本文中就是com.cohomefinder.gwt.mortgagecalculator.MortgageCalc.nocache.html。
   载入gwt模块时只要在host page里申明一个meta标签就可以了。meta 的name属性是“gwt:module”,content属性是模块的完整名字。

//
//
 ModuleControlBlocks
//
function  ModuleControlBlocks()  {
  
this.blocks_ = [];
}

ModuleControlBlocks.dynamicResources_ 
=   new  DynamicResources();  //  "static"
ModuleControlBlocks.prototype  =   {} ;

/**
 * Adds a module control control block for the named module.
 * @param metaElem the meta element that caused the module to be added
 * @param name the name of the module being added, optionally preceded by
 * an alternate base url of the form "_path_=_module_".
 
*/

ModuleControlBlocks.prototype.add 
=   function (metaElem, name)  {
  
var mcb = new ModuleControlBlock(metaElem, name);
  
this.blocks_ = this.blocks_.concat(mcb);
}
;

/**
 * Determines whether all the modules are loaded and ready to run.
 
*/

ModuleControlBlocks.prototype.isReady 
=   function ()  {
  
for (var i = 0, n = this.blocks_.length; i < n; ++i) {
    
var mcb = this.blocks_[i];
    
if (!mcb.isReady()) {
      
return false;
    }

  }

  
  
// Are there any pending dynamic resources (e.g. styles, scripts)?
  if (!ModuleControlBlocks.dynamicResources_.isReady()) {
    
// No, we're still waiting on one or more dynamic resources.
    return false;
  }


  
return true;
}


/**
 * Determines whether there are any module control blocks.
 
*/

ModuleControlBlocks.prototype.isEmpty 
=   function ()  {
  
return this.blocks_.length == 0;
}


/**
 * Gets the module control block at the specified index.
 
*/

ModuleControlBlocks.prototype.get 
=   function (index)  {
  
return this.blocks_[index];
}


/**
 * Injects an iframe for each module.
 
*/

ModuleControlBlocks.prototype.injectFrames 
=   function ()  {
  
for (var i = 0, n = this.blocks_.length; i < n; ++i) {
    
var mcb = this.blocks_[i];

    
// Insert an iframe for the module
    var iframe = document.createElement("iframe");
    
var selectorUrl = mcb.getBaseURL() + mcb.getName() + ".nocache.html";
    selectorUrl 
+= "?" + (__gwt_isHosted() ? "h&" : "" ) + i;
    
var unique = new Date().getTime();
    selectorUrl 
+= "&" + unique;
    iframe.style.border 
= '0px';
    iframe.style.width 
= '0px';
    iframe.style.height 
= '0px';
    alert(selectorUrl);
    
// Fragile browser-specific ordering issues below
    
/*@cc_on
    // prevent extra clicky noises on IE
    iframe.src = selectorUrl;
@
*/

    
    
if (document.body.firstChild) {
      document.body.insertBefore(iframe, document.body.firstChild);
    }
 else {
      document.body.appendChild(iframe);
    }

    
/*@cc_on
    // prevent extra clicky noises on IE
    return;
@
*/


    
if (iframe.contentWindow) {
      
// Older Mozilla has a caching bug for the iframe and won't reload the nocache.
      iframe.contentWindow.location.replace(selectorUrl);
    }
 else {
      
// Older Safari doesn't have a contentWindow.
      iframe.src = selectorUrl;
    }

  }

}


/**
 * Runs the entry point for each module.
 
*/

ModuleControlBlocks.prototype.run 
=   function ()  {
  
for (var i = 0, n = this.blocks_.length; i < n; ++i) {
    
var mcb = this.blocks_[i];
    
var name = mcb.getName();
    
var frameWnd = mcb.getModuleFrameWindow();
    
if (__gwt_isHosted()) {
      
if (!window.external.gwtOnLoad(frameWnd, name)) {
        
// Module failed to load.
        if (__gwt_onLoadError) {
            __gwt_onLoadError(name);
        }
 else {
            window.alert(
"Failed to load module '" + name + 
            
"'. Please see the log in the development shell for details.");
        }

      }

    }
 else {
      
// The compilation itself handles calling the error function.
      frameWnd.gwtOnLoad(__gwt_onLoadError, name);
    }

  }

}
   
ModuleControlBlocks不是 ModuleControlBlock的一个集合,并且会负责将控制快所描述的模块载入并运行。每一个gwt模块都运行在单独的iframe中。

history.html:

com.cohomefinder.gwt.mortgagecalculator.MortgageCalc.nocache.html:

    这个文件是一个加载代理,它是与浏览器无关的代码。由于目前市场上浏览器的种类繁多。所以GWT在编译时会产生针对不同浏览器的不同版本的JS生成文件。而模块加载程序首先加载的就是这个不一览浏览器的代码文件,其中包含了的程序可以根据浏览器的种类,再由它来选择的和浏览器有关的那份代码。

31B37A91E12073356EFED6A87DDD05BB.cache.html:
    针对gecko1_8
或者 gecko浏览器的JS生成文件。
992FF46E12A7705BC86ACDF2A5956B7C.cache.html:
    针对ie6
的JS生成文件。
BC136B40572B863559384961791144CA.cache.html:
   
针对 safari 的JS生成文件。
77A54215924094616B0083B14A757399.cache.html:
   
针对 opera 的JS生成文件。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值