J engine -构建高性能、可监控的前端应用框架
description
Transcript of J engine -构建高性能、可监控的前端应用框架
jEngine--构建高性能、可监控
的前端应用框架
王涛2012-03-02
应用框架—解决应用的实际问题
应用复杂,开发者多,需要引入模块化编程
需求紧,无遐优化,框架需要真正的 fast by default
单点故障多,可用性不高,应用的容错性要增强
浏览器多样,调试不便,引入统一的分层log机制
前端代码无日志, 线上故障发现晚, 急需异常监控系统
整体框架图
沙箱(core.sandbox.js)
应用核心(core.application.js)
FDEV4
首屏加载
模块
延迟加载
模块
延迟初始
化模块
https://github.com/wtxidian/jEngine
模块化编程—模块
模块:
• 模块对整体架构的了解非常有限,它只知道sandbox的存在。
• 每个模块各司其职,共同构建了应用的正常运行。
模块化编程—模块代码示例!(function($){
var Sandbox,
configs = {
end:0
};
function lazyloadModule1(sb) {
Sandbox = sb;
return lazyloadModule1;
}
$.extend(lazyloadModule1,{
init:function(cfg){
this.config = $.extend(true, {}, configs, cfg);
Sandbox.on( Searchweb.Config.Events.DELETE, this.create);
},
create:function(data){
alert("lazyloadModule1 got the message:" + data.msg);
},
end:0
});
Searchweb.Business.lazyloadModule1 = lazyloadModule1;
})(jQuery);
模块化编程—模块
模块必须呆在相应的sandbox中,也许会
很不舒服,但这对应用是安全的!
模块化编程—模块设计原则
不要在模块中创建全局变量。
禁止访问该模块之外的Dom节点。
只允许调用自身的或是sandbox提供的方法。
不可直接引用其它模块的对象或调用其方法。
Sandbox是通往外界的桥梁!
模块化编程—沙箱
• 沙箱负责模块间的数据传递及事件交互
沙箱模块1 模块2
notify on
notifyon
模块化编程—沙箱
Module1:
var data={msg:"send from Module1"};
Sandbox.notify (Searchweb.Config.Events.DELETE, data);
Module2:
Sandbox.on ( Searchweb.Config.Events.DELETE, this.callback);
模块化编程—应用核心
模块生命周期管理 异常处理
消除SPOF
监控
容错
性
注册
初始化
运行停止
销毁
模块化编程—应用核心代码示例register: function(moduleId, creator, opt){
moduleData[moduleId] = {
creator: creator,
instance: null
};
},
start: function(moduleId){
moduleData[moduleId].instance = moduleData[moduleId].creator(new Sandbox(this));
moduleData[moduleId].instance.init();
},
stop: function(moduleId){
var data = moduleData[moduleId];
if (data.instance){
data.instance.destroy();
data.instance = null;
}
}
模块化编程—应用核心代码示例
//注册所有首屏加载模块
AppCore.register("mod-search-module1", Searchweb.Business.Module1);
AppCore.register("mod-search-module2", Searchweb.Business.Module2);
AppCore.register("mod-search-module3", Searchweb.Business.Module3);
AppCore.register(“mod-search-module4”, Searchweb.Business.Module4, {callback:function(){/* */}});
//初始化所有首屏加载模块
AppCore.startAll();
<div id=“mod-search-module1" data-mod-config=
'{"name":"title","url":"http://china.alibaba.com/offer/post/json/validate_result.htm"}„>
…
</div>
性能提升—Fast By Default
• 在模块管理中加入“懒注册”机制,从框架的层面解决性能
问题 -- Fast By Default!
模块注册
首屏加载
模块注册
延迟加载
模块注册
延迟初始化
模块注册
性能提升—Fast By Default
/**
*@method: lazyRegister 延迟(加载|初始化)模块注册函数
* @param: moduleId: 注册模块的名称(string)
* @param: creator: 模块的构造函数(string|function),如果为string,则会被parse成为function
* @param: els: 触发延迟加载模块的元素,可以是id、dom、domArray(jquery dom数组对象)
* @param: event: 延迟加载的驱动事件,可以是曝光事件、dom事件、manual事件{exposure|manual|normalevents like: click, mouseover, focus, mouseenter}
* @param: opt : (optional)延迟加载成功后的回调函数{Object}
*/
lazyRegister: function(moduleId, creator, els, event, opt){
var succeed = false;
if(opt.init === false){
succeed = jEngine.Core.LazyModule.register(els, event, opt);}else{
var self = this;
succeed = jEngine.Core.LazyModule.register(els, event, opt, function(){self._lazyStart(moduleId, creator)});
}
return succeed;
}
性能提升—Fast By Default
lazyLoadModuleInit:function(){
//曝光延迟加载模块的注册方式
AppCore .lazyRegister(“mod-search-lazyload1”, “Searchweb.Business.lazyloadModule1”, $(".domDetail"), 'exposure',{
threshold:200,module:this.config.lazyurl.lazyModule1
});
//交互事件驱动延迟加载模块的注册方式
AppCore .lazyRegister("mod-search-lazyload2", "Searchweb.Business.lazyloadModule2", '#mod-search-lazyload2', 'mouseover',{
module:this.config.lazyurl.lazyModule2});
//使用代码主动触发的延迟加载模块的注册方式 Sandbox.notify("jEngine.lazyLoad", moduleId);
AppCore.lazyRegister("mod-search-lazyload3",
"Searchweb.Business.lazyloadModule3", null, 'manual',{
module:this.config.lazyurl.lazyModule3});
},
性能提升—Fast By Default模块注册的三种方式统一定义在一个文件中:
性能提升—Fast By Default
<html>
<body>
… 省略 …
<!--页面上只应该有一个js文件被放置在<script>标签中加载,其余都是无阻塞加载-->
<script type=“text/javascript” src=“http://style.china.alibaba.com/js/app/search/v4.0/core/core.seed.js”></script>
<script>
jEngine.Core.Loader.js(“http://style.china.alibaba.com/js/lib/fdev-v4/core/fdev-min.js”).js(“http://style.china.alibaba.com/js/app/search/v4.0/core/core.logger.js”).js(“http://style.china.alibaba.com/js/app/search/v4.0/core/core.sandbox.js”).js(“http://style.china.alibaba.com/js/app/search/v4.0/core/core.lazymodule.js”).js(“http://style.china.alibaba.com/js/app/search/v4.0/core/core.application.js”)//核心类加载完毕,开始加载业务类
.js(“http://style.china.alibaba.com/js/app/search/v4.0/example/config.js”)
.js(“http://style.china.alibaba.com/js/app/search/v4.0/example/module1.js”)
.js(“http://style.china.alibaba.com/js/app/search/v4.0/example/lazyinitmodule.js”)
.js(“http://style.china.alibaba.com/js/app/search/v4.0/example/app.start.js”);
</script>
</body>
</html>
性能提升—Fast By Default
完美的js加载瀑布图:
便于开发调试—分层log机制
Firefox:
IE:
修改自叶周全分层log类,添加了IE下的log机制:
增强容错性—全局性异常处理
区分线上线下模式的方法:var DEBUG_MOD = (typeof window.dmtrack ==="undefined") ? true : false;
try{
…
}
catch (ex) {
if(!DEBUG_MOD){
$.logger.error(“log error message:” + ex.message); //线上模式记录异常
}else{
throw ex; //debug模式下抛异常给浏览器
}
}
增强容错性—全局性异常处理var instance = new module.creator(sb), name, method;instance.options = opt;
//debug模式下try catch不起作用,交由浏览器自己处理错误。
//online模式下可以把错误信息记录在日志服务器上。
if (!DEBUG_MOD){for (name in instance){
method = instance[name];if (typeof method == "function"){
instance[name] = function(name, method){return function (){
try { return method.apply(this, arguments);
}catch(ex) {
$.logger.error(moduleId + " throw error: " + name + "()-> " + ex.message); }
};}(name, method);
}}
}return instance;
增强容错性—全局性异常处理
• 模块中的每个函数都被自动加入到异常处理机制中。
• 线上异常的定位可以非常迅速。
异常监控—与Dragoon的完美结合
//online模式下针对warning和error才需要报警
if(!DEBUG_MOD){
if(level == 0 || level == 1){
(new Image()).src = $.Logger.errorUri + this.getBrowserInfo() + errorMsg;
}
}
异常监控—与Dragoon的完美结合
异常监控—与Dragoon的完美结合
• 更加完善的前端异常监控系统
后期完善方向
• 性能优化结合后端的继续深入
• 模块化编程更完善的支持