前端性能优化

性能调优包括那些方面?

从广义的层面来看,就不仅限于程序内部了,因为造成系统性能问题的瓶颈很可能来源于方方面面,而这种情况往往是性能调优很普遍的情况

2016020131.jpg

从狭义的范畴来看,性能调优主要是指通过修改软件程序逻辑、结构等技术手段提升软件产品的各项性能指标,如响应时间等

性能的参考指标

执行时间:一段代码从开始运行到运行结束所使用的时间。

CPU时间:(算法)函数或者线程占用CPU的时间。

内存分配:程序在运行时占用的内存空间。

磁盘吞吐量:描述I/O的使用情况。

网络吞吐量:描述网络的使用情况。

响应时间:系统对某用户行为或者动作做出响应的时间。响应时间越短,性能好。

阮一峰性能优化(浏览器的渲染机制、重排、重绘)

要理解网页性能为什么不好,就要了解网页是怎么生成的。网页的生成过程,大致可以分成五步。

bg2015091501.png

HTML代码转化成DOM

CSS代码转化成CSSOM(CSS Object Model)

结合DOM和CSSOM,生成一棵渲染树(包含每个节点的视觉信息)

生成布局(layout),即将所有渲染树的所有节点进行平面合成

将布局绘制(paint)在屏幕上

这五步里面,第一步到第三步都非常快,耗时的是第四步和第五步。

"生成布局"(flow)和"绘制"(paint)这两步,合称为"渲染"(render)。

bg2015091502.png

样式表越简单,重排和重绘就越快。

重排和重绘的DOM元素层级越高,成本就越高。

table元素的重排和重绘成本,要高于div元素

提高性能的九个技巧

第一条是上一节说到的,DOM 的多个读操作(或多个写操作),应该放在一起。不要两个读操作之间,加入一个写操作。

第二条,如果某个样式是通过重排得到的,那么最好缓存结果。避免下一次用到的时候,浏览器又要重排。

第三条,不要一条条地改变样式,而要通过改变class,或者csstext属性,一次性地改变样式。

第四条,尽量使用离线DOM,而不是真实的网面DOM,来改变元素样式。比如,操作Document Fragment对象,完成后再把这个对象加入DOM。再比如,使用 cloneNode() 方法,在克隆的节点上进行操作,然后再用克隆的节点替换原始节点。

第五条,先将元素设为display: none(需要1次重排和重绘),然后对这个节点进行100次操作,最后再恢复显示(需要1次重排和重绘)。这样一来,你就用两次重新渲染,取代了可能高达100次的重新渲染。

第六条,position属性为absolute或fixed的元素,重排的开销会比较小,因为不用考虑它对其他元素的影响。

第七条,只在必要的时候,才将元素的display属性为可见,因为不可见的元素不影响重排和重绘。另外,visibility : hidden的元素只对重绘有影响,不影响重排。

第八条,使用虚拟DOM的脚本库,比如React等。

第九条,使用 window.requestAnimationFrame()、window.requestIdleCallback() 这两个方法调节重新渲染(详见后文)。

性能优化指南

依据数据而不是凭空猜测

这是性能优化的第一原则,当我们怀疑性能有问题的时候,应该通过测试、日志、profillig来分析出哪里有问题,有的放矢,而不是凭感觉、撞运气。

忌过早优化

在我的工作环境(以及典型的互联网应用开发)与编程模式下,追求的是快速的迭代与试错,过早的优化往往是无用功。而且,过早的优化很容易拍脑袋,优化的点往往不是真正的性能瓶颈。

忌过度优化

性能优化的目标是追求合适的性价比。

在不同的阶段,我们对系统的性能会有一定的要求,比如吞吐量要达到多少多少。如果达不到这个指标,就需要去优化。如果能满足预期,那么就无需花费时间精力去优化,比如只有几十个人使用的内部系统,就不用按照十万在线的目标去优化。而且,后面也会提到,一些优化方法是“有损”的,可能会对代码的可读性、可维护性有副作用。这个时候,就更不能过度优化。

深入理解业务

代码是服务于业务的,也许是服务于最终用户,也许是服务于其他程序员。不了解业务,很难理解系统的流程,很难找出系统设计的不足之处。

性能优化的层次

按照我的理解可以分为需求阶段,设计阶段,实现阶段;越上层的阶段优化效果越明显,同时也更需要对业务、需求的深入理解。

需求阶段

需求是为了解决某个问题,问题是本质,需求是解决问题的手段。

需求分析对性能优化有什么帮助呢,第一,为了达到同样的目的,解决同样问题,也许可以有性能更优(消耗更小)的办法。这种优化是无损的,即不改变需求本质的同时,又能达到性能优化的效果;第二种情况,有损的优化,即在不明显影响用户的体验,稍微修改需求、放宽条件,就能大大解决性能问题。PM退步一小步,程序前进一大步。

需求讨论也有助于设计时更具扩展性,应对未来的需求变化。

网络加载类

首屏数据请求提前,避免JavaScript文件加载后才请求数据

首屏加载和按需加载,非首屏内容滚屏加载,保证首屏内容最小化

模块化资源并行下载

inline首屏必备的CSS和JavaScript

meta dns prefetch设置DNS预解析

资源预加载

合理利用MTU策略

缓存类

合理利用浏览器缓存(http缓存、app缓存、浏览器缓存)

静态资源离线方案

图片类

图片压缩处理(裁剪)

使用较小的图片,合理使用base64内嵌图片

在页面使用的背景图片不多且较小的情况下,可以将图片转化成base64编码嵌入到HTML页面或CSS文件中,这样可以减少页面的HTTP请求数。需要注意的是,要保证图片较小,一般图片大小超过2KB就不推荐使用base64嵌入显示了。

使用更高压缩比格式的图片

图片懒加载

使用Media Query或srcset根据不同屏幕加载不同大小图片

使用iconfont代替图片图标

定义图片大小限制

加载的单张图片一般建议不超过30KB,避免大图片加载时间长而阻塞页面其他资源的下载,因此推荐在10KB以内。如果用户上传的图片过大,建议设置告警系统,帮助我们观察了解整个网站的图片流量情况,做出进一步的改善。

架构协议类

ssr

seo优化

减少白屏时间

利用服务端缓存

设置max-age|expires进行优化网站

网页的缓存是由 HTTP 消息头中的 “Cache-control” 来控制的,常见的取值有 private、no-cache、max-age、must-revalidate 等,默认为private。

打开新窗口

如果指定cache-control的值为private、no-cache、must-revalidate,那么打开新窗口访问时都会重新访问服务器。而如果指定了max-age值,那么在此值内的时间里就不会重新访问服务器

在地址栏回车

如果值为private或must-revalidate(和网上说的不一样),则只有第一次访问时会访问服务器,以后就不再访问。如果值为no-cache,那么每次都会访问。如果值为max-age,则在过期之前不会重复访问。

按后退按扭

如果值为private、must-revalidate、max-age,则不会重访问,而如果为no-cache,则每次都重复访问

按刷新按扭

无论为何值,都会重复访问

  • 发表于:
  • 原文链接:https://kuaibao.qq.com/s/20190115G1BJ1G00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券