简单汇总了一下web的优化方案(主要的前端优化策略)
- 减少http请求次数
- 文件合并(js、css、图片);ps:多个图片合并之后,总体积会变小
- 内联图片,即data:URL scheme,但容易导致html页面混乱
- 可缓存的ajax
- 尽量使用get而不是post,get仅发送一次TCP数据包,而post会发送两次
- 使用专用的静态服务器域名,这样在请求静态文件时,就不会传递cookie了,节省带宽
- 推迟加载内容
- 如动画等,可以等页面必备的逻辑执行完后再执行动画
- 预加载
- 空闲的时候,加载接下来可能用到的东西
- 无条件的预加载
测试代码index.html
onload中进行图片预加载
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<script>
function parseDom(arg) {
let objE = document.createElement("div");
objE.innerHTML = arg;
return objE.childNodes[0];
};
window.addEventListener('load',function(){
let loader = document.getElementById('preload');
loader.append(parseDom('<img src="pic/IMG_20170914_115807.jpg"/>'));
})
</script>
<body>
<a href="2.html">去下一个页面</a>
<div id="preload" style="display: none;"></div>
</body>
</html>
2.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<body>
<img src="pic/IMG_20170914_115807.jpg"/>
</body>
</html>
访问首页时,进行预加载jpg
访问2.html时,就不需要再次加载了,加快了响应速度
- 有条件的预加载:根据用户的操作预测接下来可能访问的东西,提前加载资源
- 减少dom的数量,检测数量 document.getElementsByTagName('*').length ,数量多造成reflow慢、元素定位慢
- 使用CDN
内容分发网络(Content Delivery Network,CDN)是由一系列分散到各个不同地理位置上的Web服务器组成的,它提高了网站内容的传输速度。用于向用户传输内容的服务器主要是根据和用户在网络上的靠近程度来指定的。例如,拥有最少网络跳数(network hops)和响应速度最快的服务器会被选定。
- 避免使用css expression,因为表达式需要实时更新,使计算次数非常频繁
- 使用外部js和css,因为浏览器可以对其进行缓存,多页面复用同一个文件的时候效果明显
- 对js和css文件进行压缩
- css放在顶端head标签内
- 把可以延迟执行的js放在底部,因为默认情况下script标签的下载和执行都是同步的,想要动态加载script,可以使用第三方的lab.js
- 网上还有说把js打包成png的,看了评论感觉实用性不是很大,压缩效率和gzip差不多,而且好像出现中文内容,就会打包失败,还要求支持canvas(IE8以上)
- 尽量少用全局变量,容易出现混乱而且不易于回收(除非你手动删除),容易造成内存泄漏
- 对于重复运行的代码,用setInterval而不是用setTimeout
- 语句数量最小化
/**不提倡**/
var i = 1;
var j = "hello";
var arr = [1,2,3];
var now = new Date();
/**提倡**/
var i = 1,
j = "hello",
arr = [1,2,3],
now = new Date();
/**不提倡**/
var name = values[i];
i++;
/**提倡**/
var name = values[i++];
- 过深的原型链也会导致效率低下
- 设置动画元素为absolute或fixed
position: static
或position: relative
元素应用动画效果会造成频繁的reflow
。
position: absolute
或position: fixed
的元素应用动画效果只需要repaint
。
- 尽量把多个操作放到一个timer中,而不是使用多个timer
- 字符串连接采用Array.join而是使用+,前者不会创建临时对象,能降低垃圾回收的开销【不同浏览器实现方式不同,因此有不同的争议】
- 性能上来说:
""+字符串
>String()
>.toString()
>new String()
。 - dom对象与js对象相互引用、事件绑定等容易造成内存泄漏,因为dom对象一般不会被销毁,除非你去删除dom
- 多个元素的点击事件转换为一个父容器的点击事件,可提高效率
- 尽量在循环外部使用tryCatch(个人理解就是catch语句块会创建一个作用域,循环中创建作用域导致性能低下)
- 对dom定位时,尽量在某个父容器中进行搜索,减小搜索范围
- 减少使用with,with有自己的作用域,会增加作用域链的长度,优化策略是减小作用域的长度,降低作用域链上的搜索时间
dom节点优化
节点优化的关键在于降低reflow次数,先了解以下什么是reflow【可理解为刷新重绘等】
accepted
|
|
1.使用 DocumentFragment 可以减少reflow次数
2. css优化
-
如以下代码逐条更改元素的几何属性,理论上会触发多次
reflow
。element.style.fontWeight = 'bold' ; element.style.marginLeft= '30px' ; element.style.marginRight = '30px' ;
-
可以通过直接设置元素的
className
直接设置,只会触发一次reflow
。element.className = 'selectedAnchor' ;
3.当dom元素比较多的时候,可以对要频繁操作的dom元素进行缓存,而不是每次都进行定位
4.innerHTML创建dom的效率要大于createElement()和appendChild()和document.write
5.避免的空的src和href,空的代表加载当前页面,这是没有必要的
6.多innerHTML的多次赋值转换为一次赋值,可降低reflow
var str = "<div>这是一个测试字符串</div>";
/**效率低**/
var obj = document.getElementsByTagName("body");
for(var i = 0; i < 100; i++){
obj.innerHTML += str + i;
}
/**效率高**/
var obj = document.getElementsByTagName("body");
var arr = [];
for(var i = 0; i < 100; i++){
arr[i] = str + i;
}
obj.innerHTML = arr.join("");
闭包优化
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = (function(index) {
return function(evt) {
output.innerText += 'Clicked ' + events[index];
};
})(i);
}
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = (function(event) {
return function(evt) {
output.innerText += 'Clicked ' + event;
};
})(events[i]);
}
以上两段代码的区别:前者对event形成依赖,而后者不会。当外部的event被修改了或者被删除了,前者由于形成了依赖,无法正常工作,而后者没有依赖,可以正常执行