前端性能优化4部曲35条优化手段

218 阅读8分钟

1、性能优化的价值

注意性能优化的价值和指标不是一回事,指标通常来说提高多少时间,价值指的是业务价值,说白点就是money和用户数。

说这个是,我们要有一个认知,业务价值高于性能优化指标,你可以这么理解,性能优化服务于业务价值。你的性能优化做得再好,如果没有在2方面提高,那也白搭,甚至如果你无法证明性能优化提高业务价值,那也白搭。

可能很多人听过这个说法,1个页面如果超过4s显示,用户就会离开。这个怎么证明了?很多文章都是轻描淡写给结论,也不知这个结论正确与否。

假设你是负责人,技术优化是消耗人力,产品给到需求也消耗人力,那么产品需求和技术优化冲突了,这个时候做抉择话,我相信负责人肯定选择业务价值高的产品需求,从而推掉技术优化 。在假设你是一名普通前端开发,想做性能优化那你做的第1件事,证明性能优化能够带来业务价值,说服领导和产品们。

我这里给一个例子,如何证明性能优化提高业务价值:我们有个购买商品的页面,访问该页面的性能指标中,有个95线时间,我在性能时间高于95线埋1个点,在和性能时间低于95线也埋1个点,分别统计高于95线和低于95线的商品的购买成功率,结果发现低于95线的时间,商品购买成功率高于xx%。

2、性能的指标

2.1 性能指标

Performance API感官性能优化指标 很多地方都有讲解,我就不过多描述了。我只说一点,很多团队定指标计算公式拿其中xxx - xxx,我们要弄清楚,所属团队的标计算公式是什么,不要盲目参考主流,以自身团队的为主,其他为辅

2.1.1 Performance API

image.png

const timingInfo = window.performance.timing; 
// TCP连接耗时
timingInfo.connectEnd - timingInfo.connectStart
// DNS查询耗时
timingInfo.domainLookupEnd - timingInfo.domainLookupStart;
// 获得首字节耗费时间,也叫TTFB
timingInfo.responseStart - timingInfo.navigationStart
// domReady时间(与前面提到的DomContentLoad事件对应)
timingInfo.domContentLoadedEventStart - timingInfo.navigationStart
// DOM资源下载
timingInfo.responseEnd - timingInfo.responseStart

2.1.2 感官性能优化指标

  • First Paint(简称FP):表示文档中任一元素首次渲染时间。
  • First Contentful Paint(简称FCP):当浏览器首次渲染任何文本,图像(包括背景图像),非白色画布或SVG时。这个指标就是我们日常说的白屏时间。
  • First Meaningful Paint(简称FMP):首次有意义的绘制,这个指标反映的是主要内容出现在页面上所需要的时间,如果FMP时间过长的话,这里就要考虑是不是静态文件阻塞了主线程。
  • ……

2.2 性能指标工具

  • chrome Performance
  • LightHouse
  • chrome coverage (覆盖率)
  • chorme network (红蓝线,DOMContentLoaded和Load)

这几种具体使用,略。

着重强调一下覆盖率,我们按需引入做的好不好,有一大程度看覆盖率。

image.png

3、性能监控和分析

上面说的指标,仅仅说的单个用户单次访问页面的性能指标,每个用户访问的设备的是有差异。所以,需要统计所有用户的性能指标,作为性能优化指导,即性能监控。

在性能监控针对所有用户,得增加群体的性能指标,常见的:

  • 最大值(Max)
  • 最小值(Min)
  • 中位数(Median)
  • 平均值(Mean)
  • 90线(90th Percentile)
  • 95线(95th Percentile)
  • 99线(99th Percentile)
  • 50线(50th Percentile)

除了这些,还要做环境的区分,在微信渠道、app渠道、pc渠道、支付宝渠道等。我遇到特别坑例子,我负责的一个页面,在微信流量巨大,然而是按照我司的性能计算公司得出首屏95线,微信渠道的是app渠道的2倍左右。

当然这些东西,可以都有可视化界面。具体怎么研发,这些都是架构平台方面,作为一个业务开发的我,理解的比较浅显,这里给1个参考文章美团性能优化之路——性能指标体系

如何使用平台提供性能监控工具,不区分架构研发和业务开发,上面提到的监控指标,业务开发也应该熟悉。

总而言之,性能优化的三部曲,监控->分析->优化。对于大多数开发来说,性能监控参与比较少,几乎没有,对于分析、优化,这个都是可以参与,我想说明【优化】是性能优化最后一步,但对于监控、分析是不忽视。

ps: 如果加上性能价值,应该4部曲,价值 -> 监控 -> 分析 -> 优化。

4、性能优化

性能优化的手段,我分为2类——技术层面、业务层面。

4.1 技术层面

对于技术层面上的,列一个清单,只要做了就能或多或少带来性能提升。说白点,在技术层面上性能优化做的好不好,很大程度取决于清单列的全不全。

【性能优化清单表格地址】

表格截图

image.png

总共26条,表格实在太大,只好贴截图,。这里强调 2 点: 第 1 点

如果能用配置解决就用配置,不能的话,应该定制规范。尤其 css 这块,见过很多人不在乎,瞎定规则。

其中大部分是webpack配置,可以参考我的一个vue-cli项目源码,参考源码

第 2 点

动态加载和懒加载,可以理解为延迟加载,想想哪些东西可以这样做?我想到4个,图片、loadScript、Vue 动态加载组件(包含普通组件、页面组件),vuex store 动态加载和延迟注册。其中vuex 普通组件动态加载,和 vuex store 很多文章比较少提及。

vuex 普通组件动态加载

<template>
  <div>
    <button @click="toggleArticleList">显示/隐藏文章列表</button>
    <component v-if="isShowArticleList" :is="currentComponent" />
  </div>
</template>



<script>
import { mapState, mapActions } from 'vuex'

export default {
  // ...
  methods: {
  // ...
    async toggleArticleList () {
      if (!this.currentComponent) {
        const component = await import(/* webpackChunkName: "homeArticleList" */'../components/home/articleList.vue')
        this.currentComponent = component.default || component
      }

      this.isShowArticleList = !this.isShowArticleList
    }
  }
}
</script>

vuex store 延迟注册

// store.js
import { userAccountModule } from './modules/userAccount'
export const store = new Vuex.Store({
  modules: {
    user: userAccountModule, 
  }
})

// Admin.vue
import adminModule from './admin.js'
export default { 
  // other component logic
  mounted () { 
    this.$store.registerModule('admin', adminModule)
  },
  beforeDestroy () {
   this.$store.unregisterModule('admin')
  }

vuex store 动态加载

// store.js
import { userAccountModule } from './modules/userAccount'
export const store = new Vuex.Store({
  modules: {
    user: userAccountModule, 
  }
})

// Admin.vue
<template>
    <button @click="toggleArticleList">显示/隐藏文章列表</button>
</template>

import adminModule from './admin.js'
export default { 
  // other component logic
  methods: { 
    toggleArticleList() {
        this.isRgisterModueEnd = true
        this.$store.registerModule('admin', adminModule)
        this.$store.dispatch('fetchRequest1')
    }
  },

  beforeDestroy () {
     this.$store.unregisterModule('admin')
  }

4.2 业务层面

当我们技术层面做了足够多努力之后,发现性能还是上不去。可以从业务上考虑,我是从角色考虑——产品、后端、前端

序号角色分类节点是否done
1产品转链接像协议、规则说明的,利用平台转成1个可配置页面
2转图片广告位能用配置图片,坚决不开组件。记得这个图片要做压缩,这个贼容易完
3登录登录返回,尽量不重新刷页面
4后端接口合并多个接口能弄成一个就弄成1个
5接口性能优化后端接口性能超过100ms,通通催他们优化
6前端并发请求多个请求没依赖,进行并发,如果其中某几个有依赖,这几个组成一个串行的异步函数,和其他请求并发
7减少请求埋点请求,尽量使用一次上传多个埋点方法
8广告位置请求,尽量使用一次获取多个广告请求
9日志,尽量上传错误日志

4.2.3 重点问题——日志影响性能

这里着重说明,性能优化一大块是接口请求的日志,带来的性能问题。

一个接口请求的日志,通常来说有下面几个

  • 正常入参
  • 正常出参
  • 异常入参
  • 异常出参
  • 请求方法异常

99%情况以上的会有入参正常、出参正常的日志,相当2个请求,也就是说1个接口请求会有2个日志请求,5个话就是15个(像这样页面,我负责过还不少),极具影响性能,且后端也做了正常入参、正常出参的日志,完全是重复工作。

所以,大多数情况下只需做异常情况的,在有需要情况做正常日志。那这个怎么解决了,我个人期望2个解决方案:

  • 白名单控制,用户在白名单内,就上传正常入参、正常出参的日志,否则不上传
  • 灰度有入参正常、出参正常的日志,生产环境不需要

当然也可以把2个方案综合。

5、总结一下

  • 性能优化实际4部曲, 价值 -> 监控 -> 分析 -> 优化
  • 技术层优化,26条手段,能配置解决尽量配置,不能定规范
  • 业务层面优化,9条手段,接口请求的日志是性能大问题

参考文章

Vue 性能优化:如何实现延迟加载和代码拆分
写给中高级前端关于性能优化的9大策略和6大指标 | 网易四年实践

(end)