QWrap入门之apps种子应用

就像是一棵树有很多果实一样,QWrap也有很多apps,本文讲解种子应用。“种子”是沿用YUI3的说法,种子应用是解决模块加载问题的应用,包括:模块预加载、异步按需加载、模块应用。

apps果实篇之:种子

或许有些同学对异步加载模块不大熟悉,没关系,我们先感性的看一下这段代码

 
 
 
  1.  
  2.  
  3.  
  4. QW应用之一:seed_youa  
  5.  
  6.  
  7.  
  8.  
  9. div1-----时间
 
  • div2-----时间
  •  
  •  
  •  
  • function test(){  
  •     QW.use('jQuery,YouaCore',function(){  
  •         $('#div1').css('color','red').find('>.content').html(new Date()+'');//这段代码用到了jquery用法  
  •         W('#div2').css('color','blue').query('.content').html(new Date().format('YYYY-MM-dd hh:mm:ss'));//这段代码用到了Youa版的QWrap  
  •     });  
  • }  
  •  
  •  
  • 1. 如果用户浏览此网页时,只加载了一个体积很小的seed_youa.combo.js这个js(其实就是seed_youa.js(http://dev.qwrap.com/resource/js/apps/seed_youa.js)),这个js经yui压缩后的大小为4K。

    2. 当用户点击按钮时,按钮对应的js用到jQuery与YouaCore,点击后才会去加载那两个jQuery与YouaCore对应的js,之后才有运行效果。

    3. 第二次点击按钮,由于前面已经加载过js,所以这次会直接运行按钮事件。

    分析一下以上三步,分两种情况。

    A. 对于只进行了第一步操作的用户,他们用seed_youa.js替代了jQuery与YouaCore两个js的流量(这是好处甲);

    B. 对于进行过第二步操作的用户,由于以上流量的节约,会让用户提前能够点击按钮(这是好处乙),点击后异步加载需要的js,加载完后事件才运行,即点击与运行存在一个时间差(这是坏处甲),并且三个js都用到了,相对于传统写法,http多了一个seed_youa.combo.js(这是坏处乙)。

    另外,对于页面程序员来说,他在写按钮事件时,只需要知道自己的这段js用到了哪些模块,而不用关心这些模块是否已经加载(这是好处丙),不过,他引用模块的方式有了一些变化(少键入html代码,多键入js代码)。

    好处甲、好处乙、好处丙、坏处甲、坏处乙,还有些没有分析到的好处与坏处,反正有利有弊。

    那么,在什么情况下利大于弊、什么情况下弊大于利,而我们该如何兴利除弊?

    如果这个页面的用户100%不会点击按钮,则几乎没坏处,只有好处甲、好处丙。

    如果页面100%的用户会点击按钮,则需要权衡再权衡利弊再想办法。

    好的,我们先暂且搁置这些细节,因为以上内容已足够让同学们对“异步按需加载”有了感性的认识。我们把提供这种异步按需加载的js叫种子(seed)。

    我们看一下seed_youa.js,它是一个组合js(即前面一篇文章所说的B类apps:开发时可以是多个文件,但上线时会先合并后上线。)

    它由三个js组成:

     
     
     
    1. document.write('<\/script>');  
    2. document.write('<\/script>');  
    3. document.write('<\/script>') 

    core/core_base.js是QWrap的主干js
    core/module.h.js是模块管理器,也是一个Helper,提供三个方法:addConfig、use、provide,代码参见:http://dev.qwrap.com/resource/js/core/module.h.js
    youa_modules_config.js是youa项目只所使用到的常用模块配置,通过addConfig进行模块配置,代码如下:

     
     
     
    1. /*Lib Module*/ 
    2. QW.ModuleH.addConfig({  
    3.     YouaCore: {  
    4.         url: '//apps/core_dom_youa_lazy.combo.js',  
    5.         loadedChecker:function(){  
    6.             return !!(QW.W);  
    7.         }  
    8.     },  
    9.     Ajax: {  
    10.         url: '//components/ajax/ajax.youa.js',  
    11.         requires: 'YouaCore' 
    12.     },  
    13.     Anim: {  
    14.         url: '//components/animation/anim.js',  
    15.         requires: 'YouaCore' 
    16.     },  
    17.     Cookie: {  
    18.         url: '//components/cache/cache.js',  
    19.         requires: 'YouaCore' 
    20.     },  
    21.     Storage: {  
    22.         url: '//components/cache/cache.js',  
    23.         requires: 'YouaCore' 
    24.     },  
    25.     Drag: {  
    26.         url: '//components/drag/drag.js',  
    27.         requires: 'YouaCore' 
    28.     },  
    29.     Editor: {  
    30.         url: '//components/editor/editor.js',  
    31.         requires: 'YouaCore,Panel' 
    32.     },  
    33.     Panel: {  
    34.         url: '//components/panel/panel.js',  
    35.         requires: 'YouaCore' 
    36.     },  
    37.     Suggest: {  
    38.         url: '//components/suggest/suggest.js',  
    39.         requires: 'YouaCore' 
    40.     },  
    41.     "Switch": {  
    42.         url: '//components/switch/switch.js',  
    43.         requires: 'YouaCore' 
    44.     },  
    45.     Tree: {  
    46.         url: '//components/tree/tree.js',  
    47.         requires: 'YouaCore' 
    48.     },  
    49.     Valid: {  
    50.         url: '//components/valid/valid.js',  
    51.         requires: 'YouaCore' 
    52.     },  
    53.     jQuery: {  
    54.         url: 'http://common.cnblogs.com/script/jquery.js',  
    55.         loadedChecker:function(){  
    56.             return !!(window.jQuery && window.jQuery.fn);  
    57.         }  
    58.     }  
    59. });   
    60.  
    61. /*Logic Module*/ 
    62. QW.ModuleH.addConfig({  
    63.     "User": {  
    64.         url: '//global/userv3.js',  
    65.         requires: 'YouaCore',  
    66.         loadedChecker: function() {  
    67.             return !!window.topbar;  
    68.         }  
    69.     },  
    70.     ShopMap: {  
    71.         url: '//sp/map/shopmap.js',  
    72.         requires: 'YouaCore' 
    73.     }  
    74. }); 

    看到这个配置文件的同学也许会问:模块添加得越来越多会怎么办?为什么不像YUI一样,在各个模块的js里进行addConfig,而要集中起来addConfig?

    不错,理论上是会越来越大,但是,实际上最大能大到多少?并且不一定是所有的模块配置都要放在这里面。在页面的js里也可以QW.addConfig('MyPageJs','//my.js')的。所谓的太大,只是个理论问题,不是个实际问题。

    YUI在各个模块的js里进行add,有好处,也有坏处。

    好处就是多了个沙箱机制,沙箱理论看起来很严谨,可以满足YUI的严谨性洁癖----其实我一直没有理解它对实用者都有啥好处。

    而坏处,也有很多。例如:

    1.  需要模块的代码来适应他的加载机制。----例如,jQuery也可以算是个模块,凭什么要让独立的jquery来改代码?

    2.  假设我改了jQuery的代码来适应这loader,那是不是也损失了jQuery的原来的用法,即预加载模式用法(在HTML的Header里引用jquery.js,在页面直接用$('#id').show())。

    3.  例如use('Editor',function(){})时,其实由于依赖关系,会按需加载YouaCore,Drag,Panel,Editor四个js,因为依赖关系是在各自的js里,理论上无法将四个请求合并成一个请求,也无法在请求editor.js时就并行请求drag.js。

    4.  如果客户端缓存了js,我们更新Editor.js后,use('Editor',function(){})无法知道是否需要在editor.js后添加版本号。

    5.  如果有复合模块,例如core_dom_youa_lazy.js其实是同时拥有很多小模块功能的一个js,那在drap.js里如何定义依赖?

    而QWrap的“集中配置”方式,上面几条都不是什么问题。

    对于第一条第二条,已经解决,即:addConfig时的loadedChecker参数。

    例如,这样配置jQuery:

     
     
     
    1. QW.ModuleH.addConfig({  
    2.     jQuery: {  
    3.         url: 'http://common.cnblogs.com/script/jquery.js',  
    4.         loadedChecker:function(){  
    5.             return !!(window.jQuery && window.jQuery.fn);  
    6.         }  
    7.     }  
    8. });  

    这个jQuery引用的是博客园网站的,我们没有作任何修改。

    如果页面已经预加载了jquery,运行QW.use('jQuery',function(){})也不会再次加载jquery.js。

    当然,用户还可以保持习惯,用以前的预加载经典用法。

    对于第三条合并请求与并行请求,QW目前还没做,不过,只需调整一下module.h.js里的某一段代码即可。在源代码里有说明:

     
     
     
    1. function loadsJsInOrder() {  
    2.       //浏览器不能保证动态添加的ScriptElement会按顺序执行,所以人为来保证一下  
    3.       //参见:http://www.stevesouders.com/blog/2009/04/27/loading-scripts-without-blocking/  
    4.       //测试帮助:http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=3&jsdelay=0&n=1&t=1294649352  
    5.       //todo: 目前没有充分利用部分浏览器的并行下载功能,可以改进。  
    6.       //todo: 如果服务器端能combo,则可修改以下内容以适应。  
    7.       var moduleI = loadingModules[0];  
    8.       function loadedDone() {  
    9.           moduleI.loadStatus = 2;  
    10.           var cbs = moduleI.__callbacks;  
    11.           for (var i = 0; i < cbs.length; i++) {  
    12.               cbs[i]();  
    13.           }  
    14.           isLoading = false;  
    15.           loadsJsInOrder();  
    16.       }  
    17.       if (!isLoading && moduleI) {  
    18.           //alert(moduleI.url);  
    19.           isLoading = true;  
    20.           loadingModules.splice(0, 1);  
    21.           var checker = moduleI.loadedChecker;  
    22.           if (checker && checker()) { //如果有loaderChecker,则用loaderChecker判断一下是否已经加载过  
    23.               loadedDone();  
    24.           } else {  
    25.               loadJs(moduleI.url.replace(/^\/\//, QW.PATH), loadedDone);  
    26.           }  
    27.       }  
    28.   } 

    对于第四条缓存,由于是统一配置,所以只需在发布时,在配置文件的js后面加上对应js的md5码的前N位即可。

    例如,线上的配置可能是:

     
     
     
    1. Ajax: {  
    2.       url: '//components/ajax/ajax.youa.js?111111.js',  
    3.       requires: 'YouaCore' 
    4.   },  
    5.   Anim: {  
    6.       url: '//components/animation/anim.js?222222.js',  
    7.       requires: 'YouaCore' 
    8.   } 

    页面引用的种子,也是在后面加上它的md5码的前N位。

    这样做的好处是:每次上线后,用户也只需下载有过修改的js。

    对于第五条的复合模块问题,由于是统一配置,所以根本就不是问题。

    说了seed_youa.js的这么多好处,当然还要说明一个限制:项目中需要有一个水平还过得去的js同学,来负责这个统一的模块配置文件。

    关于module.h.js还有挺多内容要讲的,不过,绝大同学不用关心它的实现;关心他的实现的同学大多也看过NK行的YUI3种子,再看这个两百行的module.h.js,应该是小case,这里先略过。

    小结一下,QWrap的这个种子应用是绿色版的,并且小巧、灵活,可以直接复制过去引用。不过需要注意一下你所放的路径,防止QW.PATH的值计算有误,或者强制改掉QW.PATH的值。

    附:QWrap网址:http://www.qwrap.com

    原文:http://www.cnblogs.com/jkisjk/archive/2011/04/15/qwrap_apps_seed_youa.html

    新闻名称:QWrap入门之apps种子应用
    标题链接:http://www.hantingmc.com/qtweb/news48/450398.html

    网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

    广告

    声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

    猜你还喜欢下面的内容

    搜索引擎优化知识

    分类信息网站