前端|前端性能优化-综合篇

网络+资源 1.减少/延缓HTTP请求

  • 尽可能合并静态资源图片、JavaScript或CSS代码,多个小文件合并为一个大文件,减少页面请求数和资源请求消耗。
  • VUE项目中也可以采用路由懒加载、图片懒加载vue-lazyload插件,这样可以缩短首屏加载时间。
2.使用HTTP/2
  • 解析速度快:HTTP/2 增加了新的二进制分帧数据层,是基于帧的协议。采用分帧是为了将重要信息封装起来,让协议的解析方可以轻松阅读、解析并还原信息。
  • 多路复用:HTTP/2 的二进制分帧层突破了这一限制,所有的请求和响应都在同一个 TCP 连接上发送:客户端和服务器把 HTTP 消息分解成多个帧,然后乱序发送,最后在另一端再根据流 ID 重新组合起来。
    (流:HTTP/2 规范对流的定义是:HTTP/2 连接上独立的、双向的帧序列交换。如果客户端想要发出请求,它会开启一个新流,然后服务器在这个流上回复。 由于有分帧,所以多个请求和响应可以交错,而不会互相阻塞。流 ID 用来标识帧所属的流。)
    ——流量控制:由于一个 TCP 连接流量带宽(根据客户端到服务器的网络带宽而定)是固定的,当有多个请求并发时,一个请求占的流量多,另一个请求占的流量就会少。流量控制可以对不同的流的流量进行精确控制。
    ——优先级:通过 HEADERS 帧和 PRIORITY 帧,客户端可以明确地和服务器沟通它需要什么,以及它需要这些资源的顺序。具体来讲,服务器可以根据流的优先级,控制资源分配(CPU、内存、带宽),而在响应数据准备好之后,优先将最高优先级的帧发送给客户端。
    ——服务器推送:HTTP2 新增的一个强大的新功能,就是服务器可以对一个客户端请求发送多个响应。换句话说,除了对最初请求的响应外,服务器还可以额外向客户端推送资源,而无需客户端明确地请求。
    ——其他性能优化:无需合并资源(把多个小资源合并成一个大资源,从而减少请求)、取消域名拆分(不需要采取多个域名来突破浏览器 TCP 连接数限制)
  • 首部压缩:HTTP/2 在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送。
对比 HTTP/1.1 HTTP/2
格式 文本 二进制
解析速度 慢:必须不断地读入字节,直到遇到分隔符 CRLF 为止 快:每个帧都有表示帧长度的字段。
多路复用 否:如果客户端想发送多个并行的请求,那么必须使用多个 TCP 连接 是:可以在共享连接上同时发送多个请求和响应
首部压缩 否:携带大量冗余头部信息 是:对于相同的头部数据,不再重发
参考链接: 半小时搞懂 HTTP、HTTPS和HTTP2
3.静态资源使用 CDN + 单独域名
  • 内容分发网络(CDN)是一组分布在多个不同地理位置的 Web 服务器。我们都知道,当服务器离用户越远时,延迟越高。CDN 就是为了解决这一问题,在多个位置部署服务器,让用户离服务器更近,从而缩短请求时间。
  • 单独域名有利于静态资源做CDN缓存
4.文件压缩
  • 前端压缩JS\CSS\HTML插件:
    JavaScript:UglifyPlugin
    CSS :MiniCssExtractPlugin
    HTML:HtmlWebpackPlugin
  • 服务端配置支持gzip压缩资源传输的方式
    前端则可以通过向 HTTP 请求头中的 Accept-Encoding 头添加 gzip 标识来开启这一功能。
5.善用缓存 尽量避免重复的资源,防止增加多余请求。
  • 通用消息头部 Cache-Control 其中有两个选项:
    1.max-age: 设置缓存存储的最大周期,超过这个时间缓存被认为过期(单位秒)。在这个时间前,浏览器读取文件不会发出新请求,而是直接使用缓存。
    2.no-cache: 指定 no-cache 表示客户端可以缓存资源,每次使用缓存资源前都必须重新验证其有效性。
  • VUE项目中可以使用 keep-alive 缓存不活动的组件。
图片
  1. 字体图标代替图片图标,减少请求
  2. 图片小于2k情况下,合理使用base64内嵌图片 url-loader
  3. 图片懒加载 vue-lazyloader
  4. 图片预加载:可以在window.onload之后请求一些其他地方需要的图片资源
  5. 较大的图片可先在css设定大小,减少图片加载过程带来的重排重绘
  6. 图片压缩
JS
  1. 慎用全局变量
  2. 节流、防抖
  3. 采用事件委托,减少监听量,节省内存
  4. 数组按行扫描
  5. 合理缓存DOM对象,对常用的DOM避免每次使用时都要从整个DOM树中重新查找。
  6. 不覆盖原生方法
  7. 字面量与构造式。数组、对象、字符串等,直接声明比new 更快。
  8. 使用web worker
    web worker是运行在后台的js,独立于其他脚本,不会影响页面你的性能。并且通过postMessage将结果回传到主线程。这样在进行复杂操作的时候,就不会阻塞主线程了。
  9. 尽量少用JS动画,JS直接操作DOM极容易引起页面的重排
参考链接:
  • 前端性能优化24条建议
CSS
  1. 浏览器解析CSS选择器遵循从右向左解析的原则,选择器越短越好,尽量避免在选择器末尾添加通配符。
  2. 选择器优先级:内联 > ID选择器 > 类选择器 > 标签选择器,尽量使用高优先级的选择器,例如 ID 和类选择器。
  3. 使用 transform 和 opacity 属性更改来实现动画,不会触发重排重绘
  4. 减少使用CSS import 导入CSS,尽量用 link 链接引入CSS。当 HTML 文件被加载时,link 引用的文件会同时被加载,而 @import 引用的文件则会等页面全部下载完毕再被加载;
  5. 提取多个重复的内联样式。
DOM
  1. 减少重排重绘
  2. 尽量避免使用table、iframe
    table内容的渲染是将table的DOM渲染树全部生成完并一次性绘制到页面上的,所以在长表格渲染时很耗性能,应该尽量避免使用它,可以考虑使用列表元素 ul 代替;尽量使用异步的方式动态添加iframe,因为iframe内资源的下载进程会阻塞父页面静态资源的下载与CSS及HTML DOM的解析;
  3. 减少DOM深度及DOM数量
VUE
  1. v-for 遍历必须为 item 添加 key
    在列表数据进行遍历渲染时,需要为每一项 item 设置唯一 key 值,方便 Vue.js 内部机制精准找到该条列表数据。当 state 更新时,新的状态值和旧的状态值对比,较快地定位到 diff 。
  2. 长列表性能优化
    通过 Object.freeze 方法来冻结一个对象,一旦被冻结的对象就再也不能被修改了,禁止vue劫持该数据,造成不必要的监听。this.users = Object.freeze(users);
  3. 频繁切换DOM时用v-show,少或几乎不切换时用v-if
  4. computed和watch的区分使用:
    ——computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算。
    ——watch: 更多的是观察的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
  5. 事件销毁:在JS内使用的监听方法或timer在组件销毁前手动移除。
  6. 使用 keep-alive 缓存不活动的组件。
  7. 路由懒加载
  8. 图片懒加载vue-lazyloader
  9. 第三方插件按需引入
【前端|前端性能优化-综合篇】参考链接:vue项目优化

    推荐阅读