本文主要讨论界面反应慢的问题,所以只涉及前台优化,想了解后台优化的,请绕行,3Q
项目框架:S2SH+ExtJS3.2.1
背景:
1)主界面采用上下分块。主界面jsp里,上部是头,做菜单栏。下部是个div,div里嵌入了一个iframe。
这个iframe的作用,就是点击菜单栏里某一个模块,把对应模块的jsp赋给iframe的src。
模块的jsp,采用viewport组件完成布局。模型大概的样子:左侧是子菜单,右侧是子菜单的内容区。当点击左侧的子菜单时,异步加载该子菜单的业务js,完成右侧区域的布局和展示,最终完成业务功能。
好了,大概的情况已介绍完毕。
不可否认的,这样做的好处是:可以异步、动态加载相应模块的业务js;
更不可否认的,这样做的坏处是:
iframe始终是个内存隐患;
异步、动态加载模块的jsp,也就意味着,模块的jsp也要重新加载一遍所有的ext js文件。
所以,这种上部top菜单栏、下部份左(子菜单)右(业务区)的框架和效果,看起来很美,但实际APP带来的确实性能的损耗!
现状:
对于我们这个MIS,客户的感受就是一个字:慢!具体三个字:反应慢!
令人抓狂,令人崩溃,令人欲罢不能……好吧,试着分析原因~~~
有篇文章说的挺好,介绍“慢”的情况,见:http://www.blogjava.net/paulwong/archive/2011/04/21/348750.html
其实具体到项目,上面这个是从技术角度看待的,有很好的参考和衡量价值。
先放着,继续往下,还是要从项目框架入手~~~
在我们这个MIS,自己写了一套异步加载业务js的过程控件,然后利用装载控件,把业务里声明的各ext控件装载给viewport。
那么这个“慢”就局限在两个方面了:
1、加载慢?
2、渲染慢?
不猜测,科学点分析(拿出证据来)。
使用httpwatch查看模块加载文件的过程,发现了2个很大的问题:
一、top里加载了一遍ext的所有文件,然后具体模块的jsp里也加载了一遍。
这就是说:要减少加载,即减少request请求。
对策:
1)模块的jsp是一定要用到所有ext的文件的,所以尽量减少top里引用ext的情况,使之0使用ext。
2)模块的jsp里加载的js,使用yui压缩js,减少体积。
二、请求和download的过程很快,文件阻塞的情况并不是想象的那么糟。慢,其实是在渲染的过程!
在整个download的过程的监视中,所有文件请求的很快,二次加载一般都是走cache了。但是,界面还是迟迟没展现,停了3秒左右,布局才展现出来。
毫无疑问,加载和渲染,出了很大的问题!
那么可能出现的情况:
1、异步加载的控件,加载业务js慢?
2、业务js布局深度太深,导致异步加载的控件在new业务js对象后,推给viewport后展现时反应慢?(有大神说,ext的布局深度不超过5,是最好的优化,哪位同学来指点一二吧。。。)
好吧,继续走我们的科学探索分析之路-(妈妈说会使用工具的,不是动物)
使用ajax-trace(全名忘记了),跟踪渲染的过程,发现上面2个问题,都存在。
最严重的是,业务panel的布局深度超过了7,渲染到界面上,好慢好慢啊~~~哪位同学来指点一二布局吧。。。
布局深度太大,导致整个panel渲染items的时候,像爆米花那样等加载完了才一次性蹦出来(展示到界面),让人有些振奋的说,可是也太慢了~~
后来,发现了ext有个util工具箱,里面有个延迟加载的组件。
貌似有救了~~好吧,改业务panel的items加载方式:先不加载items,等待一个时间后再把这个items的内容渲染给panel。
于是,熟悉ext的同学会举手反对了:
1)你为什么不使用afterrender呢?即给panel加一个afterrender监听,等加载好panel再把items塞给panel展示;
2)等待一个时间是多久?
我的回答:
1)afterrender是同步加载,Ext.util.Delay...是异步加载;暂时这么理解吧
2)即使afterrender,界面那一坨,还是像爆米花一样蹦出来,而不是阶梯、有序地展现;
3)把items塞给panel,等待的时间可以是0可以是1,DIY,please。
4)关于那句“把items塞给panel展示”,其实是:
panel.add(XX);panel.doLayout(XX);再来句:panel.sync();好了。
删除一个组件:panel.remove(YY);panel.doLayout(YY);再来句:panel.sync();
总结一下吧:
1)减少请求数,即减少加载的文件数量;
2)压缩加载的文件,可以使用YUI+ant压缩;
有人说ext那么大,我就用window组件了,能定制这一个多好?
好,有定制ext控件的哟,请看:http://www.javaeye.com/topic/445480
3)延迟加载交互数据,如含有store的一些控件都在点击的时候再去后台取数据,毕竟数据量不大;
4)延迟布局,阶梯式展现;
其实,还有下面的问题和方法,不过目前只在实验阶段:
1)使用filter,开启tomcat对js\css等文件的缓存机制;
目前tomcat已经达到2G内存了,这缓存,赖着不走了~~~
2)内存泄漏问题
这个是最头疼的。在IE6下,好多控件,动不动就会产生leak节点、cycle节点,真FUCK!!
再科学点,用sieve这个工具查看哦
解决之道:override控件,如panel、window等,释放内存。
做这个要采用打patch的方式进行,目前[align=left][/align]我就在做这个事~~给大家点参考:
http://wenku.baidu.com/view/044e62186bd97f192279e94e.html
http://hi.baidu.com/davice_li/blog/item/61bc1717fdf85114962b43a1.html
http://blog.csdn.net/zhangxin09/article/details/5031465
http://ext.group.iteye.com/group/topic/10537
http://www.iteye.com/topic/466766
内存释放需要注意以下几点:
1.window的销毁:如果创建window时不加renderTo, window会渲染到页面body中,如果自己不销毁的话会越积越多。
2.控件如果是渲染到dom元素上而不是Ext容器上,需要手动销毁。
3.创建出来的组件没被使用或没有渲染,也需要手动销毁。
4.自定义的组件如果还包含其他组件,需要自己实现销毁方法。
5.store用完以后需要销毁,可以直接用autoDestroy配置项。
其实js对象的销毁对速度影响不是特大,渲染才是大问题。保持一个干净dom比什么都强。
对了,还有iframe内存泄漏的问题,参考:
http://www.cnblogs.com/ailiangwu/archive/2008/12/04/1347314.html
http://topic.csdn.net/t/20061024/17/5106041.html