注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

西岭雪

有时命运的戏谑就在于,你一直犹豫不决,等到终于下定决心,已经到了谢幕的时间

 
 
 

日志

 
 
关于我

在虚拟的网络中,我们与缘分同行,没有擦肩 ,却留下瞬间的惊喜 ,没有见面,却在心中留存一个身影 不知对方姓甚名谁却会淡淡的牵挂默默的关注

网易考拉推荐

页面优化细节  

2010-04-14 10:46:43|  分类: 搜索优化 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

优化如何起头,怎么起头,以及做些什么还是值得思量的。

优化的一些准则:
1 优化是继续存在的,当你起头做一个功效的时候,优化就起头了。而我们往往觉得新做的功效就是一个优化好的功效,殊不知这个功效或者会影响到其他的功效,
或者先把功效做到70%,稍后再去优化也不迟。
2 不到万不得已的时候不要去优化。用户对于性能是有必然的忍耐性的,有时一个小小的加载图标就能让用户感觉很满足的。
3 优化时需要写下用例来驱动,什么条件下测试的效果如何,有了测试用例,我们才干做到有的放矢;优化时需要 保存系统的一个快照;有了这些历史信息我们才干更好的去对照,去寻找不足和需要持续优化的处所。
4 优化需要针对的是系统的瓶颈所在,找到系统的性能瓶颈,攻破他,我们得到的是事半功倍的效果 。

对于一个网站的页面优化又该从何入手呢?
一个web网站的页面的生命周期有3个阶段:
1 加载
2 渲染
3 响利用户的交互

针对这三个阶段需要 采纳不同优化策略:
1 对于加载阶段:
加载的核心是网络传输,因此重点就是将页面折腾到最小、放到离用户最近的处所,这样加载就快了。具体的实行细则可以参考:yahoo的14条建议
摘要如下:
折腾小的话,需要将页面中无用的信息去掉,gzip收缩。
1)采纳 yui compressor来进行收缩 css和js等
2)合并js和css文件,应用 jsmin等工具
3)收缩图片,合并背景图。常用工具PngCrush、PngOptimizer。
4)延迟加载,等用户用到了相应的素材时才对素材进行加载。
离用户最近的话,那就是用户的涉猎器cache了,所以要设置页面元素的尽量长的过期光阴,能够cache的统统cache住,能够放到cdn的都放到cdn上去

2 对于渲染阶段:
渲染阶段的核心是让用户尽快的看到页面的展现 ,能够与页面进行交互,因此重点是显示首屏的内容,让用户提早的能够看到页面,感受交互。
1 页面首屏先显示出来的话,需要 将js代码的事件处理 在dom树构建好之后,如同jquery的ready事件。
2 对于html中一些默认可以不关闭的标签,尽早的关闭掉,这样也有助于进步渲染的速度。如果让涉猎器去确定 何时关闭才是ok的,那需要 不少的回溯操作,花费 不少的代价。
msdn上有详细的描绘 Close Your HTML Tags
Unlike XML, HTML has the notion of implicitly closed tags. This includes frame, img, li, and p. If you don't close these tags, Internet Explorer renders your pages just fine. If you do close your tags, Internet Explorer will render your pages even faster.
3 一些大图片的延迟加载。由于涉猎器并发的连接 有限,对于一些大图片会被block住,所以尽量的延迟加载,或者按需加载,渲染的速度也会快一些
4 将web服务器缓冲区中的内容尽早的输出,会提涉猎器起头渲染的光阴。
5 页面首屏的显示尽量不要依附于js代码。这一点很首要,这样做的话,你的一些css和js就可以延迟加载进来,而不影响首屏的展现
6 页面onload的时候可以考虑 做一些预加载的事情,把一些其它页面需要 用到的素材预先加载进来。搜索引擎如google,yahoo都这样做的,悄悄的加载一些大的背景图进来。

<script>

window.onload = function () {
var script = document.createElement("script");
script.src = ...;
document.body.appendChild(script);
};

</script>

4 对于运行阶段:
运行阶段的核心是对js代码的优化,根据 js代码的履行原理,写出高效的js代码来。
1)变量应用就近原则
js有作用域链的概念,如果本作用域找不到,就会到上一个作用域去找,如果过多的应用全局变量,就会导致每次应用变量都要去层层的反省各个作用域,性能花费 不菲啊。
声明变量时记得要加上var,否则这个变量会被放到window这个顶级作用域下
不要应用 with来遍历,它会禁止 js履行器从本地来查找,而是遍历作用链来查找。
对于一些不得不用的全局变量,利用 局部变量来缓存它
var arr = ...;
var globalVar = 0;
(function () {
var i;
for (i = 0; i < arr.length; i++) {
globalVar++;
}
})();

var arr = ...;
var globalVar = 0;
(function () {
var i, l, localVar;
l = arr.length;
localVar = globalVar;
for (i = 0; i < l; i++) {
localVar++;
}
globalVar = localVar;
})();
2)对于prototype链也是一样,尽量的避免prototype链的遍历

function A () {}
A.prototype.prop1 = 1;

function B () {
this.prop2 = 2;
} B.prototype = new A();

var b = new B();
alert(b.prop1);

从b读取属性prop1,就需要 从b的prototype链遍历到a的ptototype链,想想如果链很长的话,效果会如何呢

3)还是prototype,如果要创立许多的对象,建议将对象的公共法子 放到prototype中,而不是放到结构函数中。
由于prototype是公用的,结构函数是每个对象都需要 初始化的,会节俭不少的内存。
这个需要 根据 情况 应用,通过prototype会增加对象成员的查找光阴。

function Foo () {...}
Foo.prototype.bar = function () {...};
function Foo () {
this.bar = function () {...};
}

4)尽量不要应用 eval,除非性能不是问题或者必须 应用 eval来解决问题。
同理在seTtimeout或者setInterval是最好应用匿名函数,应用字符串的话,会导致一次eval操作。

setTimeout(function () {
// 业务代码
}, 50);

5)字符串的连接 操作,尤其实在循环中的连接 操作,在ie的一些版本的涉猎器上会导致频繁的临时变量的拷贝(如c语言中的realloc),建议应用 Array对象的join法子 来解决。
更多可以参考javascript优化

var i, s = “”;
for (i = 0; i < 10000; i++) {
s += “x”;
}
var i, s = [];
for (i = 0; i < 10000; i++) {
s[i] = “x”;
}
s = s.join(“”);

6)除非是为了动态构建正则表达式,尽量少的应用 Regexp对象;而且为了确定 一个字符串是否匹配,建议应用 test而不是exec,exec有一些性能问题。
还有,正则表达式尽量的简略,如果繁杂的话,想想来回的字符串匹配,繁杂度进步不少。

7) 能够cache的处所尽量的应用 cache,尤其使一些循环中应用到的大数据集,相对稳固,又只是大宗的读操作。
//没有应用缓存,每次调用都要生成v
var fn = (function () {
var b = false, v;
return function () {
if (!b) {
v = ...;
b = true;
}
return v;
};
})();

//将v存储到fn中
function fn () {
if (!fn.b) {
fn.v = ...;
fn.b = true;
}
return fn.v;
}
//延迟加载
var fn = function () {
var v = ...;
return (fn = function () {
return v;
})();
};

7)对于一些大数据集的处理 ,尽量放到server中去做,js处理 大数据集没有优势。
不要让js履行导致ui被阻塞住,这个效果 就太差了。
尽量将长光阴 js代码通过头块在setTimeout中来做,每块不要超过300ms。否则用户就会有意见 了。

function doSomething (callbackFn) {

// 做一些初始化的工作
(function () {
// 做一小块工作,光阴不要长
if (termination condition) {
callbackFn();
} else {
// 履行下一个块
setTimeout(arguments.callee, 0);
}

})();
}

这和ajax的原理是一样的,多线程,分小块的去履行,进步 ui交互的效率 。

8) 原语操作比函数的性能要高很多。尽量应用原语操作
//小于操作
var a = 1, b = 2, c;
c = Math.min(a, b);
c = a < b ? a : b;
//数组操作
myArray.push(value);
myArray[myArray.length] = value;
myArray[idx++] = value;

9)少在循环或者性能要害点处应用异常处理 ,因为异常处理 需要 保存 不好的堆栈信息。
//循环中应用 try、cache不明智
var i;
for (i = 0; i < 100000; i++) {
try {
...
} catch (e) {
...
}
}

//将try、cache提取出来
var i;
try {
for (i = 0; i < 100000; i++) {
...
}
} catch (e) {
...
}

10)性能要害点处少应用 for、in,with这种操作,因为涉及到prototype链的查找
var key, value;
for (key in myArray) {
value = myArray[key];
...
}
//换成数组来操作
var i, value, length = myArray.length;
for (i = 0; i < length; i++) {
value = myArray[i];
...
}

11)在if、else的分支中如果分支一样,在外面定义它
function fn () {
if (...) {
...
} else {
...
}
}
var fn;
if (...) {
fn = function () {...};
} else {
fn = function () {...};
}

12)操作dom树的时候应用 innerHtml,一次性的结构,而不是append,每次还需要 调剂
不过应用 innerHtml也有不少的危险,比如插入script钓鱼脚本等,更多参考
The Problem With innerHTML
var i, j, el, table, tbody, row, cell;
el = document.createElement("div");
document.body.appendChild(el);
table = document.createElement("table");
el.appendChild(table);
tbody = document.createElement("tbody");
table.appendChild(tbody);
for (i = 0; i < 1000; i++) {
row = document.createElement("tr");
for (j = 0; j < 5; j++) {
cell = document.createElement("td");
row.appendChild(cell);
}
tbody.appendChild(row);
}

var i, j, el, idx, html;
idx = 0;
html = [];
html[idx++] = "

";
for (i = 0; i < 1000; i++) {
html[idx++] = "


";
for (j = 0; j < 5; j++) {
html[idx++] = "


   ";
}
html[idx++] = "

 

 


";
}
html[idx++] = "

 

 


";
el = document.createElement("div");
document.body.appendChild(el);
el.innerHTML = html.join("");

13) 修正 dom树时尽量应用 clone,而不是动态的再创立。
至少可以省去不少初始化的光阴
var i, j, el, table, tbody, row, cell;
el = document.createElement("div");
document.body.appendChild(el);
table = document.createElement("table");
el.appendChild(table);
tbody = document.createElement("tbody");
table.appendChild(tbody);
for (i = 0; i < 1000; i++) {
row = document.createElement("tr");
for (j = 0; j < 5; j++) {
cell = document.createElement("td");
row.appendChild(cell);
}
tbody.appendChild(row);
}

var i, el, table, tbody, template, row, cell;
el = document.createElement("div");
document.body.appendChild(el);
table = document.createElement("table");
el.appendChild(table);
tbody = document.createElement("tbody");
table.appendChild(tbody);
template = document.createElement("tr");
for (i = 0; i < 5; i++) {
cell = document.createElement("td");
template.appendChild(cell);
}
for (i = 0; i < 1000; i++) {
row = template.cloneNode(true);
tbody.appendChild(row);
}

14)应用 documentfragment
var i, j, el, table, tbody, row, cell, docFragment;
docFragment = document.createDocumentFragment();
el = document.createElement("div");
docFragment.appendChild(el);
table = document.createElement("table");
el.appendChild(table);
tbody = document.createElement("tbody");
table.appendChild(tbody);
for (i = 0; i < 1000; i++) {
...
}
document.body.appendChild(docFragment);

15)事件绑定的时候尽量绑定到最少的页面元素的子集。
我们用jquery的选择器,常常一下子就选择了许多的元素,each一下,然后绑定事件处理 函数。
如果选择出来的聚拢很大的话,不仅选择费光阴,绑定事件处理 操作是对比费光阴的。
适当 的时候可以借助事件的冒泡机制来实现事件的绑定。

要较快页面的显示,光有js的优化是不够的,css也需要 进行相应的优化。
css优化点:
1)css sprite合并背景图
2)js不要参与到布局中来,这样的话,在没有js的情况 下页面也能够正常的显示,
就可以吧js放到后米去加载了。
3)不要应用 ie的表达式,不要难过应用 ie的过滤器
4) 优化table的布局,让table能够在接管到整个数居前就可以进行渲染
Use table-layout:fixed
Explicitly define a COL element for each column
Set the WIDTH attribute on each col

  评论这张
 
阅读(43)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017