浅谈NIE组件加载方式的变化和原理
这里主要会说说小组组件新旧加载方式的实现方式、优缺点,以及未来展望
旧的方式
一、调用方式:
nie.use(["nie.util.share","nie.util.video"],function(){
//do something
});
典型的AMD加载方式,就是按需加载,异步回调,代表作:requirejs
二、实现原理:
//以下为简单实现原理,并非代码全部
nie.use = function(modules,callback){
//定义异步请求组件js成功数
var flags = 0;
//循环遍历组件名字,发起请求
for(var i=0;i<modules.length;i++){
//getScript为请求一个js文件,成功后回调,具体代码不罗列了
getScript("http://res.nie.netease.com/comm/js/"+modules[i]+".js",function(){
//每次请求后,成功数+1
flags++;
//判断成功总数大于等于组件数,调用成功回调
if(flags >= modules.length)callback();
});
}
}
从代码实现不难看出,组件数越多,同时发起的请求数就越多(用一下requirejs就知道了),但这不符合web优化的原则,所以加载方式上做了一些调整来解决这个问题
三、调整方式:
1、利用md5加密,把一次需要加载的组件的名字加密,然后请求md5文件名的脚本
nie.use = function(modules,callback){
var link = md5(modules.join(""));
getScript("http://res.nie.netease.com/comm/cache/"+link+".js",callback);
}
可能会奇怪?那这个加密了的md5文件的js文件哪来的?
2、服务器生成对应的md5文件
假设你需要请求"util.share"和"util.video"两个组件,加密后是:
abcdejjdkjj
(随便敲的),那么需要在服务器执行一段脚本
- 读取
util.share.js
和util.video.js
两个文件,合并成为一个文件 - 将文件名
join
一下,md5
加密,把加密后的字符串作为合并后的文件名保存 - 合并后文件存在
cache
文件夹下
四、优缺点:
AMD的方式在于按需要加载,利用上面的方式解决多次请求的问题。
如果你想加载某个组合的组件,那么需要先在服务器跑一下脚本生成这个文件出来,想更新某个组件的时候,需要把对应的相关的组合文件重新生成一遍,这样不太方便提供给随心所欲的调用者,异步调用,偶尔会出现以下的问题
//函数A和B,都需要使用video组件,习惯性的就会这样写了
function A(){
nie.use(["nie.video"],function(){
//do something
});
}
function B(){
nie.use(["nie.video"],function(){
//do something
});
}
A();
B();
新的方式
一、调用方式:
nie.define(function(){
var share = nie.require("nie.util.share");
var video = nie.require("nie.util.video");
//do something
});
典型的CMD加载方式,依赖前置,就是你引用组件的时候,就需要在这之前就加载好了,代表作:seajs
二、实现原理:
//简单实现,并非全部
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、请求方式改动
//简单实现,并非全部
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
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