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
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)
这几种具体使用,略。
着重强调一下覆盖率,我们按需引入做的好不好,有一大程度看覆盖率。
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 技术层面
对于技术层面上的,列一个清单,只要做了就能或多或少带来性能提升。说白点,在技术层面上性能优化做的好不好,很大程度取决于清单列的全不全。
表格截图
总共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)