在当前,网页上越来越重视用户体验,其中一个重要的前提就是访问速度。前端是庞大的,包括 HTML、 CSS、 Javascript、Image 。等等各种各样的资源。前端优化是复杂的,针对方方面面的资源都有不同的方式。至少80%的最终用户响应时间花在了页面中的组件(图片、脚本、样式表)。
页面方面优化
一. 减少HTTP请求
改善响应时间的最简单途径就是减少组件的数量,并由此减少HTTP请求的数量。
1 :CSS Sprites将多个图片文件合并成一个图片,利用css 的background-position进行定位
2 :资源合并与压缩,利用gulp,webpack等模块打包工具,分析模块之间的依赖,生成一个文件。
3:合理设置 HTTP缓存。HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传。缓存的力量是强大的,恰当的缓存设置可以大大的减少 HTTP请求。script和CSS写在外部文件,如果缓存下来可以减少请求http请求次数。
二:将CSS文件放在<head>标签中,
目的是为了让浏览器更早生成css样式规则树,样式规则树是浏览器分析网页对应的CSS文件生成的树,它跟网页的HTML结构没有任何关系,仅仅是CSS文件的树型结构。
要特别注意的是浏览器发现需要下载一个CSS文件时,它会马上停止渲染页面,并且在新的样式规则树未被建立前都不会再进行渲染或者更新页面,也就是CSS会阻塞页面的渲染。因此,必须尽可能精简CSS文件内容以及将CSS文件的link标签放到页面头部。
三:将script文件放在</body>下。
js的下载和执行会阻塞Dom树的构建,所以script标签放在首屏范围内的HTML代码段里会可能影响首屏的内容。在页面loading的过程中,当浏览器读到js执行语句的时候一定会把它全部解释完毕后在会接下来读下 面的内容。所以放在页面最后,可以有效减少页面可视元素的加载时间。
代码级优化
一:javascript代码优化
1 减少dom操作。
DOM操作往往是JavaScript 程序中开销最大的部分,而因访问NodeList 导致的问题为最多。NodeList 对象都是“动态的”,这就意味着每次访问NodeList 对象,都会运行一次查询。有鉴于此,最好的办法就是尽量减少DOM操作。
(1)用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能
(2)document.createDocumentFragment();新建dom片段,避免一条条插入。
var fragment_1 =document.createDocumentFragment();
fragment_1.innerHTML = ‘我是一个粉刷匠‘;
document.body.appendChild(fragment_1);
(3)函数节流
浏览器中某些计算和处理要比其他的昂贵很多。例如,DOM 操作比起非DOM 交互需要更多的内存和CPU 时间。连续尝试进行过多的DOM 相关操作可能会导致浏览器挂起,有时候甚至会崩溃。尤其在onresize 事件处理程序内部如果尝试进行DOM 操作,其高频率的更改可能会让浏览器崩溃。为了绕开这个问题,你可以使用定时器对该函数进行节流。
function throttle(method,delay){
var timer=null;
return function(){
var context=this, args=arguments;
clearTimeout(timer);
timer=setTimeout(function(){
method.apply(context,args);
},delay);
}
}
(4)使用事件代理。
利用事件冒泡的原理,让其父元素代替执行。减少时间绑定次数。
2 js代码性能
(1)少用闭包,闭包是最容易发生内存泄漏的地方。函数在执行完毕后,一般来说作用域下的变量会被释放,除非外部的某个操作会读写该作用域下的数据(即闭包)。
(2)避免使用with语句
with 语句的作用是将代码的作用域设置到一个特定的对象中。with 语句的语法如下:
with(location){
var qs = search.substring(1);
var hostName = hostname;
var url = href;
}
在性能非常重要的地方必须避免使用with 语句。和函数类似,with 语句会创建自己的作用域,因此会增加其中执行的代码的作用域链的长度。由于额外的作用域链查找,在with 语句中执行的代码。肯定会比外面执行的代码要慢。
(3)少用全局变量
.避免全局查找,可能优化脚本性能最重要的就是注意全局查找。使用全局变量和函数肯定要比局部的开销更大,因为要涉及作用域链上的查找。
(4)少用eval
应该避免使用eval,不安全,非常耗性能(2次,一次解析成js语句,一次执行)。
(5)为代码开启严格模式。
使JS编码更加规范化的模式,消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为。提高编译器效率,增加运行速度;
(6)优化循环。
1:存储length
for (var i =size; i < arr.length; i++) {}
?for循环每一次循环都查找了数组(arr)的.length属性,在开始循环的时候设置一个变量来存储这个数字,可以让循环跑得更快:
for (var i = size,length = arr.length; i < length; i++) {
}
2 :合理终止循环
必要的时候使用break终止循环,避免任务已经完成,还在无意义的循环。
二:css代码优化。
(1)减少css选择器的长度。
浏览器如何判断css选择器属于哪个元素?
从后往前判断。浏览器先产生一个元素集合,这个集合往往由最后一个部分的索引产生(如果没有索引就是所有元素的集合)。然后向上匹配,如果不符合上一个部分,就把元素从集合中删除,直到真个选择器都匹配完,还在集合中的元素就匹配这个选择器了。
合理减少css选择器的长度,有利于更快构建样式规则树。
(2)分离出公共样式。
我们在开发大型网站时,为了较少css文件的体积大小,避免样式重复书写,以及后期好维护,应抽离出公共样式。增加代码复用性。