浅谈NIE组件加载方式的变化和原理
这里主要会说说小组组件新旧加载方式的实现方式、优缺点,以及未来展望
旧的方式
一、调用方式:
1 2 3 | nie.use([ "nie.util.share" , "nie.util.video" ], function (){ //do something }); |
典型的AMD加载方式,就是按需加载,异步回调,代表作:requirejs
二、实现原理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | //以下为简单实现原理,并非代码全部 nie.use = function (modules,callback){ //定义异步请求组件js成功数 var flags = 0; //循环遍历组件名字,发起请求 for ( var i=0;i<modules.length;i++){ //getScript为请求一个js文件,成功后回调,具体代码不罗列了 //每次请求后,成功数+1 flags++; //判断成功总数大于等于组件数,调用成功回调 if (flags >= modules.length)callback(); }); } } |
从代码实现不难看出,组件数越多,同时发起的请求数就越多(用一下requirejs就知道了),但这不符合web优化的原则,所以加载方式上做了一些调整来解决这个问题
三、调整方式:
1、利用md5加密,把一次需要加载的组件的名字加密,然后请求md5文件名的脚本
1 2 3 4 5 | nie.use = function (modules,callback){ var link = md5(modules.join( "" )); } |
可能会奇怪?那这个加密了的md5文件的js文件哪来的?
2、服务器生成对应的md5文件
假设你需要请求"util.share"和"util.video"两个组件,加密后是:
abcdejjdkjj
(随便敲的),那么需要在服务器执行一段脚本
- 读取
util.share.js
和util.video.js
两个文件,合并成为一个文件 - 将文件名
join
一下,md5
加密,把加密后的字符串作为合并后的文件名保存 - 合并后文件存在
cache
文件夹下
四、优缺点:
AMD的方式在于按需要加载,利用上面的方式解决多次请求的问题。
如果你想加载某个组合的组件,那么需要先在服务器跑一下脚本生成这个文件出来,想更新某个组件的时候,需要把对应的相关的组合文件重新生成一遍,这样不太方便提供给随心所欲的调用者,异步调用,偶尔会出现以下的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 | //函数A和B,都需要使用video组件,习惯性的就会这样写了 function A(){ nie.use([ "nie.video" ], function (){ //do something }); } function B(){ nie.use([ "nie.video" ], function (){ //do something }); } A(); B(); |
新的方式
一、调用方式:
1 2 3 4 5 | nie.define( function (){ var share = nie.require( "nie.util.share" ); var video = nie.require( "nie.util.video" ); //do something }); |
典型的CMD加载方式,依赖前置,就是你引用组件的时候,就需要在这之前就加载好了,代表作:seajs
二、实现原理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | //简单实现,并非全部 nie.define = function (callback){ //定义异步请求组件js成功数 var flags = 0; //提取出nie.require的内容,callback.toString实际就是函数内容转为字符串 var requireList = callback.toString().match(/nie\.require\([^\)]+\)/g); //抽出组件明 for ( var i=0;i<requireList.length;i++){ requireList[i] = requireList[i].match(/\(([^\)]+)\)/i)[1].replace(/'| "/g," "); } //循环遍历组件名字,发起请求 for(var i=0;i<requireList.length;i++){ //getScript为请求一个js文件,成功后回调,具体代码不罗列了 getScript(" http: //res.nie.netease.com/comm/js/"+requireList[i]+".js",function(){ //每次请求后,成功数+1 flags++; //判断成功总数大于等于组件数,调用成功回调 if (flags >= requireList.length)callback(); }); } } |
跟上面的旧方式一样,都会出现同一个问题,会同时发起很多个请求,所以,做了以下几件事优化
三、调整方式:
1、推动SA那边做CDNCombo事情
让CDN支持线上文件合并,比如请求
??nie.util.share.js,nie.util.video.js
,CDN自动合并文件然后返回
2、请求方式改动
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //简单实现,并非全部 nie.define = function (callback){ //定义异步请求组件js成功数 var flags = 0; //提取出nie.require的内容,callback.toString实际就是函数内容转为字符串 var requireList = callback.toString().match(/nie\.require\([^\)]+\)/g); //抽出组件明 for ( var i=0;i<requireList.length;i++){ requireList[i] = requireList[i].match(/\(([^\)]+)\)/i)[1].replace(/'| "/g," "); } //拼接URL var link = " http: //res.nie.netase.com/comm/js/??" + requireList.join(","); getScript(link, function (){ callback(); }); } |
四、优缺点:
CMD方式依赖前置,写代码的时候就会感觉是同步执行,不用担忧异步请求和回调的问题,上面还可以添加去重、以及已经求求过的不请求等功能,减少不必要的请求;推动CDNCombo后,不再需要用服务器跑脚本,调用者也能随意组合组件请求。
这种方式就需要先请求完组件后再执行主体代码逻辑,执行时机会对比AMD来说慢,开发时候会容易规避AMD的一些写法问题。
五、展望与未来:
目前的组件加载方式,实现了类似seajs的功能,模块加载和组件加载,之后会把jquery也拆出来,只保留核心库,其它都按需要加载,不再全部打包成一个文件
PS:组件加载方式源码链接->GitLab
手机阅读请扫描下方二维码:
12345678

1
1
1
1
1
1
1
1
1
1
1
1
12345678

12345678

12345678

jhcwlghvnwoaeesooowx
12345678

12345678

12345678

12345678

12345678

12345678

1

1

1

1

1

1

1

1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1