前端性能优化总结(一)

一.减少http请求消耗资源

1.Css Sprites

css sprites是将多幅图融合到一张图片里,这样可以减少图片的请求数量,再通过css技术把想要的图片样式展示在浏览器页面上,虽然合成的图片会比较大,但这样做确实可以减少请求资源的消耗。

2.Inline Image

使用 data: URL scheme的方式将图片嵌入到页面或 CSS中,scheme有:data:image/gif;base64,base64编码的gif图片数据,
data:image/png;base64,base64编码的png图片数据,data:image/jpeg;base64,base64编码的jpeg图片数据,data:image/x-icon;base64,base64编码的icon图片数据。

这个方法不利于资源管理,却可以减少图片的请求,URL经过base64编码,内联在页面中。

3.设置http缓存

页面中存在许多不经常改变的静态资源,http缓存可以减少许多请求,合理设置缓存和长的过期时间。

ETag:首部字段 ETag 能告知客户端实体标识。它是一种可将资源以字符串 形式做唯一性标识的方式。服务器会为每份资源分配对应的 ETag 值。

If-None-Match:首部字段 If-None-Match 属于附带条件之一。它和首部字段 If-Match 作用相反。用于指定 If-None-Match 字段值的实体标记(ETag)值与 请求资源的 ETag 不一致时,它就告知服务器处理该请求。如果一致,就返回304,表示告知客户端使用自己本地的缓存。

If-Modified-Since:首部字段 If-Modified-Since,属附带条件之一,它会告知服务器若 If-Modified-Since 字段值早于资源的更新时间,则希望能处理该请求。 而在指定 If-Modified-Since 字段值的日期时间之后,如果请求的资源 都没有过更新,则返回状态码 304 Not Modified 的响应。

4.资源合理压缩

在服务器端对资源进行压缩,在浏览器端进行解压,对js,css,images文件尽可能进行合并(利用webpack和gulp等工具)。但压缩解压对服务器和浏览器有一定的压力,服务器资源不足时谨慎使用。

二.DOM方面的优化

1.尽量减少页面的重绘重排

通常在文档初次加载时,浏览器引擎会解析HTML文档来构建DOM树,之后根据DOM元素的几何属性构建一棵用于渲染的树。渲染树的每个节点都有大小和边距等属性,类似于盒子模型(由于隐藏元素不需要显示,渲染树中并不包含DOM树中隐藏的元素)。当渲染树构建完成后,浏览器就可以将元素放置到正确的位置了,再根据渲染树节点的样式属性绘制出页面。由于浏览器的流布局,对渲染树的计算通常只需要遍历一次就可以完成。但table及其内部元素除外。

重绘:通常是DOM节点的外观样式如背景色等改变时,引起的浏览器对该节点样式的重新绘制,呈现新的外观。重绘不一定带来重排

重排:渲染树需重新计算,重排一定会引起重绘。当DOM节点的尺寸改变时对这一节点的重新构建也会引起相关节点的重新构建;DOM元素的增删移动也会带来重排。如果在body最前面插入一个元素,会导致整个文档的重新渲染,而在其后插入一个元素,则不会影响到前面的元素;

减少重排重绘:

  • 将多次改变样式属性的操作合并成一次操作。结合css和js中元素的className进行改变一系列样式。
  • 将需要多次重排的元素,position属性设为absolute或fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。例如有动画效果的元素就最好设置为绝对定位。
  • 在内存中多次操作节点,完成后再添加到文档中去。例如要异步获取表格数据,渲染到页面。可以先取得数据后在内存中构建整个表格的html片段,再一次性添加到文档中去,而不是循环添加每一行。
  •  由于display属性为none的元素不在渲染树中,对隐藏的元素操作不会引发其他元素的重排。如果要对一个元素进行复杂的操作时,可以先隐藏它,操作完成后再显示。这样只在隐藏和显示时触发2次重排。
  •  在需要经常获取那些引起浏览器重排的属性值时,要缓存到变量。在进行某些属性的获取时,为了得到准确的值可能会进行重排,如offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight、getComputedStyle() (currentStyle in IE)等,多次使用的话要进行缓存。

三.JavaScript代码

1.慎用 with,减少作用域链查找

with(obj){ p = 1}; 代码块的行为实际上是修改了代码块中的执行环境 ,将obj放在了其作用域链的最前端,在 with代码块中访问非局部变量是都是先从 obj上开始查找,如果没有再依次按作用域链向上查找,因此使用 with相当于增加了作用域链长度。而每次查找作用域链都是要消耗时间的,过长的作用域链会导致查找性能下降。 因此,除非你能肯定在 with代码中只访问 obj中的属性,否则慎用 with,替代的可以使用局部变量缓存需要访问的属性。尽量使用局部变量代替全局变量,减少在作用域链上搜索标识符的时间

2.避免使用 eval和 Function

每次 eval 或Function 构造函数作用于字符串表示的源代码时,脚本引擎都需要将源代码转换成可执行代码。这是很消耗资源的操作 ,eval 函数效率特别低,由于事先无法知晓传给 eval 的字符串中的内容,eval在其上下文中解释要处理的代码,也就是说编译器无法优化上下文,因此只能有浏览器在运行时解释代码。这对性能影响很大。 Function 构造函数比 eval略好,因为使用此代码不会影响周围代码 ;但其速度仍很慢。 此外,使用 eval和 Function也不利于Javascript 压缩工具执行压缩。

3.数据访问

Javascript中的数据访问包括直接量 (字符串、正则表达式 )、变量、对象属性以及数组,其中对直接量和局部变量的访问是最快的,对对象属性以及数组的访问需要更大的开销。当出现以下情况时,建议将数据放入局部变量:

 a. 对任何对象属性的访问超过 1次 ;

b. 对任何数组成员的访问次数超过 1次 。另外,还应当尽可能的减少对对象以及数组深度查找。

4.事件代理

在javascript中,在页面渲染时添加到页面上的事件处理程序数量直接关系到页面的整体运行性能。最直接的影响是页面的事件处理程序越多,访问DOM节点的次数也就越多。另外函数是对象,会占用内存。内存中的对象越多,性能就越差。

发布了15 篇原创文章 · 获赞 21 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_41531446/article/details/86363161